
Chào các lập trình viên tương lai và những chiến binh code lão luyện! Anh Creyt đây, hôm nay chúng ta sẽ mổ xẻ một công cụ cực kỳ hữu ích trong Blade của Laravel mà nhiều bạn hay bỏ qua, hoặc dùng chưa đúng "điệu": @each. Nghe cái tên thì có vẻ đơn giản, nhưng tin anh đi, nó là một "máy dập khuôn" xịn sò giúp view của bạn chạy mượt mà và code "thơm" hơn rất nhiều đấy!
@each là gì và để làm gì?
Thực tế mà nói, trong lập trình web, chúng ta thường xuyên phải hiển thị danh sách các đối tượng giống nhau: một danh sách bài viết, một "dòng thời gian" các status, một "giỏ hàng" các sản phẩm, hay một "bảng xếp hạng" các người dùng. Mỗi đối tượng này thường có một cấu trúc hiển thị y hệt nhau, chỉ khác mỗi cái dữ liệu bên trong.
Trong khi nhiều bạn có thói quen dùng @foreach kết hợp với @include để lặp và nhúng từng phần tử, ví dụ:
@foreach ($posts as $post)
@include('partials.post_card', ['post' => $post])
@endforeach
Thì @each chính là giải pháp được sinh ra để "chuẩn hóa" và tối ưu hóa cái quy trình lặp và nhúng "đơn điệu" này. Hãy hình dung thế này: bạn có một dây chuyền sản xuất bánh quy. Thay vì mỗi lần làm một cái bánh, bạn lại phải tự tay trộn bột, cán, cắt, nướng, rồi lại lặp lại cho cái tiếp theo (giống @foreach + @include), thì @each giống như một cái máy dập khuôn tự động siêu tốc. Bạn chỉ cần "đổ" nguyên liệu (dữ liệu collection) vào, nó tự động "dập" ra hàng loạt cái bánh (partial view) giống hệt nhau, cực kỳ hiệu quả và nhanh chóng, không tốn công sức "điều khiển" từng cái một.
Nói tóm lại, @each dùng để render một collection các partial view. Nó tự động lặp qua một mảng hoặc collection và render một view con (partial) cho mỗi phần tử trong đó. Điều này giúp code của bạn gọn gàng hơn, dễ đọc hơn và quan trọng nhất là hiệu quả hơn về mặt hiệu năng so với việc dùng @foreach và @include thủ công.

Code Ví Dụ Minh Hoạ Rõ Ràng
Để minh họa, chúng ta sẽ xây dựng một danh sách các bài viết (posts) trên một trang blog.
1. Controller:
Đầu tiên, chúng ta cần một Controller để lấy dữ liệu và truyền sang view. Giả sử bạn có một PostController:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index()
{
$posts = [ // Đây là dữ liệu mẫu, trong thực tế sẽ lấy từ Database
(object)['id' => 1, 'title' => 'Học Laravel không khó', 'author' => 'Creyt', 'published_at' => '2023-10-26'],
(object)['id' => 2, 'title' => 'Mẹo tối ưu hóa Blade View', 'author' => 'Creyt', 'published_at' => '2023-10-25'],
(object)['id' => 3, 'title' => 'Sức mạnh của Eloquent Relations', 'author' => 'Creyt', 'published_at' => '2023-10-24']
];
return view('posts.index', compact('posts'));
}
}
2. Partial View (resources/views/partials/post_card.blade.php):
Đây là "khuôn mẫu" cho mỗi bài viết. Lưu ý rằng @each sẽ tự động truyền từng phần tử của collection vào partial view với tên biến mặc định là tên của partial (ví dụ: post_card -> $post_card). Tuy nhiên, bạn có thể chỉ định tên biến rõ ràng hơn.
{{-- resources/views/partials/post_card.blade.php --}}
<div class="post-card">
<h3><a href="/posts/{{ $post->id }}">{{ $post->title }}</a></h3>
<p>Tác giả: **{{ $post->author }}**</p>
<p><small>Ngày đăng: {{ $post->published_at }}</small></p>
<hr>
</div>
3. Main View (resources/views/posts/index.blade.php):
Đây là nơi chúng ta sử dụng @each.
{{-- resources/views/posts/index.blade.php --}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Danh Sách Bài Viết Của Creyt</title>
<style>
body { font-family: sans-serif; margin: 20px; }
.post-card { border: 1px solid #eee; padding: 15px; margin-bottom: 10px; border-radius: 5px; }
h3 { margin-top: 0; }
</style>
</head>
<body>
<h1>Các Bài Viết Mới Nhất</h1>
{{-- Dùng @each để render danh sách bài viết --}}
@each('partials.post_card', $posts, 'post', 'partials.no_posts')
</body>
</html>
Ở đây, cú pháp của @each như sau:
- Tham số 1:
'partials.post_card'- Đường dẫn đến partial view sẽ được render cho mỗi phần tử. - Tham số 2:
$posts- Collection hoặc mảng dữ liệu mà bạn muốn lặp qua. - Tham số 3:
'post'- Tên biến mà mỗi phần tử của collection sẽ được gán trong partial view. Trongpost_card.blade.php, chúng ta sẽ truy cập dữ liệu qua$post(thay vì$post_cardmặc định). - Tham số 4 (Tùy chọn):
'partials.no_posts'- Đây là một view sẽ được render nếu collection$postsrỗng. Cực kỳ tiện lợi để hiển thị thông báo "Không có bài viết nào" mà không cần thêm logic@ifphức tạp.
4. Empty View (Tùy chọn) (resources/views/partials/no_posts.blade.php):
{{-- resources/views/partials/no_posts.blade.php --}}
<div class="alert alert-info">
Xin lỗi, hiện tại chưa có bài viết nào được đăng cả. Hãy quay lại sau nhé!
</div>
Mẹo (Best Practices) để ghi nhớ hoặc dùng thực tế
- Hiệu năng vượt trội:
@eachđược tối ưu hóa ở cấp độ thấp trong Laravel. Nó biên dịch thành một vòng lặp PHP thuần túy, tránh được overhead của việc khởi tạo một view mới cho mỗi lần@includetrong@foreach. Điều này đặc biệt quan trọng khi bạn xử lý các collection lớn, giúp ứng dụng của bạn "nhẹ" hơn và "bay" hơn. - Đọc code như đọc thơ: Code của bạn sẽ gọn gàng và dễ đọc hơn rất nhiều. Thay vì một khối
@foreachloằng ngoằng, bạn chỉ cần một dòng@eachduy nhất, "khai báo" rõ ràng ý định của mình. - Tái sử dụng là vàng:
@eachkhuyến khích việc tạo ra các partial view nhỏ, tái sử dụng được. Mộtpost_card.blade.phpcó thể được dùng ở trang chủ, trang danh mục, hay thậm chí trong kết quả tìm kiếm. - Đừng quên tham số thứ 4: Cái view rỗng (empty view) là một "người bạn" đắc lực. Thay vì viết:
Bạn chỉ cần một dòng@if ($posts->count() > 0) @foreach ($posts as $post) @include('partials.post_card', ['post' => $post]) @endforeach @else @include('partials.no_posts') @endif@eachduy nhất. "Sạch sẽ" phải không? - Truyền thêm dữ liệu: Nếu bạn cần truyền thêm dữ liệu chung cho tất cả các partial (ví dụ: một biến
isAdminđể hiển thị nút sửa/xóa), bạn có thể truyền nó thông qua biến cục bộ trong view cha, hoặc dùngView::share(). - Khi nào không nên dùng
@each?:@each"tỏa sáng" khi mỗi phần tử trong collection được hiển thị theo cùng một cách. Nếu bạn có logic phức tạp, điều kiện hiển thị khác nhau cho từng phần tử (ví dụ: bài viết đầu tiên có layout khác, bài viết thứ 5 có quảng cáo...), thì@foreachkết hợp với@includehoặc@ifbên trong@foreachvẫn là lựa chọn linh hoạt hơn.@eachlà "máy dập khuôn", không phải "máy sáng tạo" tùy biến cao.
Ví dụ thực tế các ứng dụng/website đã ứng dụng
Hầu hết mọi ứng dụng web hiện đại đều có những phần tử lặp lại và @each (hoặc các cơ chế tương tự trong các framework khác) là xương sống để render chúng hiệu quả:
- Facebook/Twitter Feed: Mỗi bài đăng, tweet trên dòng thời gian của bạn là một "partial view". Tưởng tượng phải
@foreach+@includehàng trăm cái item trên feed thì sẽ "lag" đến mức nào! - Trang sản phẩm của Shopee/Lazada: Danh sách các sản phẩm trên trang chủ, trang danh mục, hoặc kết quả tìm kiếm. Mỗi "thẻ" sản phẩm (ảnh, tên, giá, nút thêm giỏ hàng) là một partial được render từ collection sản phẩm.
- Danh sách bình luận trên YouTube/VnExpress: Mỗi bình luận là một partial, với avatar, tên người dùng, nội dung, thời gian.
@eachgiúp hiển thị hàng ngàn bình luận mà vẫn giữ được hiệu suất. - Danh sách email trong Gmail/Outlook: Mỗi dòng trong hộp thư đến (người gửi, chủ đề, thời gian) là một partial view được render từ collection email.
Nhớ nhé các bạn, @each không chỉ là một cú pháp tiện lợi, nó là một công cụ mạnh mẽ giúp bạn viết code "sạch", "nhanh" và "chuyên nghiệp" hơn trong Laravel. Hãy "nhét" nó vào bộ "đồ nghề" của mình và dùng nó đúng lúc, đúng chỗ nhé! Anh Creyt tin là các bạn sẽ "bay" cao hơn với kỹ năng này.
Thuộc Series: Lavarel
Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!