Laravel Packages
/
September 18, 2018
Laravel View Models
The Laravel View Models by Brent Roose of Spatie is a package that can move the work you might do in a controller to a “view model”:
Have you ever made a controller where you had to do a lot of work to prepare variables to be passed to a view? You can move that kind of work to a so-called view model. In essence, view models are simple classes that take some data and transform it into something usable for the view.
A view model class is designed to house the complex logic of your views and clean up view-related logic from controllers:
class PostViewModel extends ViewModel
{
public $indexUrl = null;
public function __construct(User $user, Post $post = null)
{
$this->user = $user;
$this->post = $post;
$this->indexUrl = action([PostsController::class, 'index']);
}
public function post(): Post
{
return $this->post ?? new Post();
}
public function categories(): Collection
{
return Category::canBeUsedBy($this->user)->get();
}
}
The above view model class gets created in the controller:
class PostsController
{
public function create()
{
$viewModel = new PostViewModel(
current_user()
);
return view('blog.form', $viewModel);
}
public function edit(Post $post)
{
$viewModel = new PostViewModel(
current_user(),
$post
);
return view('blog.form', $viewModel);
}
}
And together, the view model and the controller provide your view with the following abilities:
<input type="text" value="" />
<input type="text" value="" />
<select>
@foreach ($categories as $category)
<option value=""></option>
@endforeach
</select>
<a href="">Back</a>
All public methods and properties in a view model are automatically exposed to the view.
I think this package is an excellent abstraction of this logic, and instead of passing the view model to the view, you can return a view directly like this:
class PostsController
{
public function update(Request $request, Post $post)
{
// …
return (new PostViewModel($post))->view('post.form');
}
}
And last but not least, you can expose functions which require extra parameters:
class PostViewModel extends ViewModel
{
public function formatDate(Carbon $date): string
{
return $date->format('Y-m-d');
}
}
Which you can then reference in your template:
Thanks to Brent Roose and the folks at Spatie for this excellent package! You can access the code and installation instructions from the GitHub repository spatie/laravel-view-models.