PHP và MySQL Bài 36: Blade Template - Truyền dữ liệu và Các cấu trúc điều khiển (If, Foreach)
Blade là một engine tạo template do chính Laravel phát triển (các file đều có đuôi .blade.php). Nó cho phép bạn sử dụng các biến, vòng lặp, điều kiện của PHP ngay bên trong mã HTML với một cú pháp cực kỳ ngắn gọn, thanh lịch và đặc biệt là tự động bảo mật chống XSS.
1. Cách truyền dữ liệu từ Controller sang View
Hãy quay lại file app/Http/Controllers/HomeController.php ở bài trước và sửa lại hàm index. Lần này, chúng ta sẽ tạo ra một vài biến và truyền nó sang View.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class HomeController extends Controller
{
public function index() {
// 1. Tạo một biến chuỗi (String)
$pageTitle = "Danh sách Bài viết Mới nhất";
// 2. Tạo một mảng dữ liệu mô phỏng (Trong thực tế sẽ lấy từ Database)
$posts = [
['id' => 1, 'title' => 'Laravel cơ bản', 'status' => 'published'],
['id' => 2, 'title' => 'Tìm hiểu Blade Template', 'status' => 'draft'],
['id' => 3, 'title' => 'Bảo mật API với JWT', 'status' => 'published']
];
// 3. Truyền dữ liệu sang View bằng hàm compact()
// Hàm compact('pageTitle', 'posts') sẽ tự động gom các biến thành một mảng để gửi đi
return view('home', compact('pageTitle', 'posts'));
}
}
2. In biến ra màn hình bằng Blade (Tự động chống XSS)
Trong dự án PHP thuần, để in biến $pageTitle ra màn hình một cách an toàn, bạn phải gõ: <?php echo htmlspecialchars($pageTitle); ?>.
Trong Blade, bạn chỉ cần dùng cặp ngoặc nhọn kép {{ }}:
Mở file resources/views/home.blade.php và sửa lại:
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<title> {{ $pageTitle }} </title>
</head>
<body>
<h1> {{ $pageTitle }} </h1>
</body>
</html>
Lưu ý: Cặp ngoặc
{{ }}đã được Laravel tự động bọc sẵn hàmhtmlspecialchars()ngầm bên dưới, nên bạn hoàn toàn yên tâm không bao giờ bị dính mã độc XSS.Trường hợp ngoại lệ (
{!! !!}): Nếu biến của bạn có chứa sẵn mã HTML (ví dụ:$noi_dung = "<b>In đậm</b>";) và bạn thực sự muốn trình duyệt hiểu mã HTML đó thay vì in ra dạng văn bản, bạn dùng cặp ngoặc nhọn kết hợp dấu chấm than:{!! $noi_dung !!}. (Chỉ dùng khi bạn chắc chắn 100% dữ liệu đó an toàn).
3. Cấu trúc điều kiện (@if, @elseif, @else)
Thay vì phải mở thẻ <?php if(...) { ?> nhàm chán, Blade cung cấp các "chỉ thị" (Directives) bắt đầu bằng ký tự @.
Ví dụ: Kiểm tra trạng thái của bài viết.
<!-- Dùng trực tiếp trong file home.blade.php -->
@if ($posts[0]['status'] == 'published')
<p>Bài viết này đã được xuất bản và hiển thị công khai.</p>
@elseif ($posts[0]['status'] == 'draft')
<p>Bài viết này đang nháp, chỉ admin mới xem được.</p>
@else
<p>Bài viết đã bị ẩn.</p>
@endif
4. Vòng lặp siêu việt trong Blade (@foreach và @forelse)
Đây là lúc Blade thể hiện sức mạnh tuyệt đối trong việc render danh sách dữ liệu.
Cách 1: Sử dụng @foreach truyền thống
Giống hệt vòng lặp foreach của PHP, nhưng cú pháp HTML sạch sẽ hơn rất nhiều:
<ul>
@foreach ($posts as $post)
<li>
ID: {{ $post['id'] }} - Tiêu đề: {{ $post['title'] }}
</li>
@endforeach
</ul>
Cách 2: Vũ khí tối thượng @forelse (Đặc sản của Laravel)
Khi lấy dữ liệu từ Database, sẽ có trường hợp mảng $posts bị rỗng (không có bài viết nào).
Bình thường, bạn phải viết một lệnh @if (count($posts) > 0) bọc bên ngoài vòng lặp. Nhưng với @forelse, Laravel gom cả hai thao tác này làm một:
<div class="post-list">
@forelse ($posts as $post)
<!-- Nếu mảng có dữ liệu, nó sẽ lặp qua đây -->
<div class="post-item">
<h3>{{ $post['title'] }}</h3>
<p>Trạng thái: {{ $post['status'] }}</p>
</div>
@empty
<!-- Nếu mảng rỗng (0 phần tử), nó sẽ in ra thẻ p này -->
<p>Hiện tại chưa có bài viết nào trong hệ thống.</p>
@endforelse
</div>
5. File Giao diện hoàn chỉnh sau khi kết hợp
Đây là bức tranh toàn cảnh file home.blade.php của bạn lúc này:
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<title>{{ $pageTitle }}</title>
</head>
<body>
<h1>{{ $pageTitle }}</h1>
<div class="danh-sach">
@forelse ($posts as $post)
<div style="border: 1px solid #ccc; padding: 10px; margin-bottom: 10px;">
<h2>{{ $post['title'] }}</h2>
@if ($post['status'] == 'published')
<span style="color: green;">Đã xuất bản</span>
@else
<span style="color: red;">Bản nháp</span>
@endif
</div>
@empty
<p>Dữ liệu đang trống!</p>
@endforelse
</div>
</body>
</html>
Bây giờ, nếu bạn F5 trình duyệt (http://localhost:8000/home), bạn sẽ thấy danh sách bài viết được render ra cực kỳ mượt mà.
Tổng kết Bài 36
Blade đã giải phóng hoàn toàn Backend Developer khỏi sự rối rắm khi trộn lẫn PHP và HTML. Mã nguồn của bạn bây giờ rất dễ đọc, dễ bảo trì và đặc biệt an toàn nhờ cơ chế chống XSS mặc định.
Tuy nhiên, dữ liệu ở bài này vẫn là mảng "cứng" (hard-code) do chúng ta tự gõ tay vào Controller. Đã đến lúc kết nối Laravel với kho dữ liệu MySQL để lấy thông tin thật.
All rights reserved