Làm thứ làm cho Laravel Request của bạn thú vị hơn

Làm thứ làm cho Laravel Request của bạn thú vị hơn

Hi các bạn,

Theo tư tưởng của Taylor – web development should be fun and easy to learn, thì mình nên follow cái này để làm code của chúng ta đẹp đẽ thân thiện hơn.

Ở bài này, mình sẽ cho bạn 1 ít mắm muối vào cái custom Request class của bạn, để nó ngon lành hơn nè.

Let’s roll.

Retrieve Other Models

Sự thật là khi làm 1 project, $this->route('model') thì không phải lúc nào cũng đủ, có khi ta cần load thêm 2-3 models nữa từ Request, vd:

articles/{articleId}/set-category

POST:

  • category_uuid – UUID của category cần set cho Article

Vậy khi đó mình sẽ có cái method rules như sau:

<?php

class ArticleSetCategoryRequest extends FormRequest
{
	//...
	
	public function rules(): array
	{
		return [
			'category_uuid' => 'required|exists:categories,uuid',
		];
	}
}

Thông thường, trong Controller, ta sẽ load model như vầy:

class ArticleController extends Controller
{
	public function setCategory(Article $article, ArticleSetCategoryRequest $request): JsonResponse
	{
		$category = Category::findByUuid($request->input('category_uuid'));
		
		//...
	}
}

Nhìn hổng clean lắm nhỉ, nhưng nếu ta bỏ qua Request class, nó sẽ như sau:

class ArticleSetCategoryRequest extends FormRequest
{
	public function getCategory(): Category
	{
		return Category::findByUuid($request->input('category_uuid'));
	}

Và giờ ở Controller, ta lấy Category ra:

class ArticleController extends Controller
{
	public function setCategory(Article $article, ArticleSetCategoryRequest $request): JsonResponse
	{
		$category = $request->getCategory();
		
		$article->categories()->sync($category);
	}
}

Better hơn, nhỉ? Vì khi này ta đã bưng logic qua Request và nó nên vậy, Request nên cung cấp đủ dữ liệu cho Controller trước khi xử lý.

P/s: ngoài ra bạn cũng nên implement 1 cái short-cache ở đây, nếu bạn có ý định getCategory liên tục, điều này sẽ tránh dc mỗi lần get lại tốn 1 query xuống db => slow => bad practice.

Ngoài ra, mình sure kèo Category thay vì  ?Category (nullable-type) bởi vì rules của mình có required category, nên nếu mà nó missing => lỗi 422 rồi.

class ArticleSetCategoryRequest extends FormRequest
{
	private Category $category;
	
	public function getCategory(): Category
	{
		return $this->category ??= Category::findByUuid($request->input('category_uuid'));
	}
}

Wants

Như tên của nó, Request từ client muốn BE bên mình trả về cái gì?

Ví dụ, Laravel có cái này: wantsJson , nếu mà nó returns true thì Response đó, Laravel sẽ auto parse về JSON.

Từ đó ta adapt cái terms này để làm Request của chúng ta đẹp hơn, một vài ví dụ cho bạn:

wantsArticles

Ví dụ bạn đang làm 1 endpoint GET categories/{id} , thông thường bạn chả cần  load articles làm gì. Nhưng vd 1 ngày đẹp trời bạn cần load articles của category, thì Request của bạn sẽ như sau:

class CategoryShowRequest extends FormRequest
{	
	public function wantsArticles(): bool
	{
		return (bool) $this->input('load_articles');
	}
}

Và ở Controller:

class CategoryController extends Controller
{
	public function show(Category $category, CategoryShowRequest $request): JsonResponse
	{
		if ($request->wantsArticles()) {
			$category->load(['articles']);
		}
		
		//...
	}
}

Rất clean, nhỉ?

wantsSortByHighView

Sort theo lượt views nhiều của Article?

Request:

class ArticleIndexRequest extends FormRequest
{	
	public function wantsSortByHighView(): bool
	{
		return (bool) $this->input('sort_by_high_views');
	}
}

Controller:

class ArticleController extends Controller
{
	public function index(ArticleIndexRequest $request): JsonResponse
	{
		$articlesQuery = Article::query();
		
		$articlesQuery->when(
			$request->wantsSortByHighView(),
			fn (Builder $q) => $q->orderBy('views', 'DESC')
		);
		
		//...
	}
}

// Đây là 2 ví dụ mình suy nghĩ ra dc, bạn có thể apply tương tự cho cases của bạn nhé.

Conclusions

Đây là 2 cái nho nhỏ để giúp code bạn đẹp hơn và dễ đọc hơn, để có gì có gì hay mình update típ nhá.

Happy weekend, folks!

facebook
Seth Phát

Seth Phát

Mình là Phát - biệt danh Seth Phát. Hiện đang là một Sr. Full-Stack Engineer. Mình là một người yêu thích và đam mê lập trình và hiện tại đang theo về phần Web là chủ yếu. Mạnh Back-end và khá Front-end, vẫn đang theo đều cả 2 :v. Còn gì bằng khi được làm những thứ mà mình yêu thích, đam mê ;)

Leave a Reply

Your email address will not be published. Required fields are marked *

Bình luận qua Facebook