Quản lý Logic trong View với Laravel View Model
Bài đăng này đã không được cập nhật trong 5 năm
Giới thiệu
Đã bao giờ bạn phải code và xử lý logic quá nhiều ở Controller
sau đó truyền biến qua View
không ạ? Với những trường hợp không quá phức tạp thì không sao, nhưng với View cần quá nhiều dữ liệu mà cần phải xử lý logic trong Controller
trước thì thật kinh khủng (x_X). Rất may ở đây chúng ta có một package là Laravel View Model
. Thực chất View Model
một class
trung gian giữa Controller
và View
, class
này sẽ chứa logic biến đổi dữ liệu theo dạng phù hợp với View (không hẳn là giống MVVM Pattern).
Cài đặt
Cài đặt thông qua composer
composer require spatie/laravel-view-models
Sử dụng như thế nào?
Thay vì viết toàn bộ logic xử lý cho View
ở Controller
ta sẽ viết ở View Model
, điều này giúp cho Controller
không quá cồng kềnh. Chúng ta có thể tạo 1 view model bằng cách extends từ php Spatie\ViewModels\ViewModel
.
Dưới đây là một ví dụ:
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);
//hoặc như thế này
//return (new PostViewModel($post))->view('blog.form');
}
}
Thay vì truyền biến thẳng qua view
, chúng ta truyền một view model
qua view
, trong view model này sẽ chứa logic xử lý dữ liệu cho view
.
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();
}
public function formatDate(Carbon $date): string
{
return $date->format('Y-m-d');
}
}
Ở view
có thể truy cập vào tất cả các thuộc tính và phương thức public của view model
và xử lý như bình thường với Blade Template , .
<input type="text" value="{{ $post->body }}" />
<select>
@foreach ($categories as $category)
<option value="{{ $category->id }}">{{ $category->name }}</option>
@endforeach
</select>
//truyền params vào phương thức trong view model
<span>{{ $formatDate($post->created_at) }}</span>
<a href="{{ $indexUrl }}">Back</a>
Lưu ý: Trong trường hợp HTTP Header set Content-Type
là JSON
response sẽ trả về định dạng JSON
thay vì view
đã đc render
Với JSON response
Mặc định view model
sẽ trả về dữ liệu theo định dạng JSON
, ta có thể set response là 1 instance của View Model
.
class PostsController
{
public function update(Request $request, Post $post)
{
// …
return new PostViewModel($post);
}
}
hoặc
class PostViewModel
{
// …
public function values(): array
{
return PostResource::make(
$this->post ?? new Post()
)->resolve();
}
}
Tạo view model thế nào?
Tạo một view model
bằng artisan CLI:
php artisan make:view-model HomepageViewModel
.
Mặc định HomepageViewModel sẽ có namespace là App\ViewModels
.
Kết luận
Với view model
chúng ta có thể làm cho Controller
clean hơn, một phần nào đó có thể giúp quá trình maintenance sau này bớt khổ cực
All rights reserved