Introduction
The laravel view model is a laravel package created by Brent Roose. This package can move the work into a “view model” that you might do inside a controller. The main objective of this view model is that it is designed to house the complex logic of your views and clean up view-related logic from controllers.
For instance: 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.
How does it work ?
Create a postViewModel class extending the main ViewModel class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
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(); } } |
Now, the above class will get credited in to your controller.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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); } } |
They altogether (Model view and Controller) provide your view with the following abilities.
1 2 3 4 5 6 7 8 9 10 |
<input type="text" value="{{ $post->title }}" /> <input type="text" value="{{ $post->body }}" /> <select> @foreach ($categories as $category) <option value="{{ $category->id }}">{{ $category->name }}</option> @endforeach </select> <a href="{{ $indexUrl }}">Back</a> |
This package acts as the abstraction to the logic of your view.
How ?
Well, instead of passing the view model to the view, you can return a view directly like this.
1 2 3 4 5 6 7 8 9 |
class PostsController { public function update(Request $request, Post $post) { // … return (new PostViewModel($post))->view('post.form'); } } |
Also, the function which requires extra parameters can be exposed
1 2 3 4 5 6 7 |
class PostViewModel extends ViewModel { public function formatDate(Carbon $date): string { return $date->format('Y-m-d'); } } |
Which you can then reference in your template:
1 |
{{ $formatDate($post->created_at) }} |
Refrences
Github Repository: https://github.com/spatie/laravel-view-models
Laravel News: https://laravel-news.com/laravel-view-models