Trong phát triển web, ngoài việc trả về dữ liệu API, hầu hết các tuyến đường web đều cần hiển thị giao diện người dùng. Laravel cung cấp một hệ thống mẫu mạnh mẽ gọi là Blade, giúp việc tạo và quản lý các tệp xem trở nên hiệu quả hơn.
Quản lý Tệp View
Laravel hỗ trợ ba loại tệp view chính, phân biệt qua phần mở rộng tệp:
.css: Được xử lý bởi trình duyệt..php: Được xử lý bởi trình thông dịch PHP..blade.php: Được xử lý bởi trình thông dịch Blade, cho phép sử dụng các cú pháp đặc biệt.
Trả về View và Truyền Dữ liệu
Bạn có thể trả về một view từ một route bằng hàm trợ giúp view(). Để truyền dữ liệu vào view, bạn có thể sử dụng phương thức with() hoặc truyền một mảng các cặp khóa-giá trị trực tiếp vào hàm view().
// Sử dụng hàm trợ giúp view()
Route::get('/', function () {
// Tìm kiếm tệp 'home.blade.php' hoặc 'home.php' trong thư mục resources/views
return view('home');
});
// Truyền dữ liệu với phương thức with()
return view('home')->with('tasks', Task::all());
// Truyền dữ liệu bằng mảng
return view('home', ['tasks' => Task::all()]);
Chia sẻ Biến giữa các View
Để chia sẻ dữ liệu trên nhiều view, bạn có thể sử dụng phương thức share() của đối tượng view. Điều này rất hữu ích cho các thành phần lặp lại như header, footer hoặc thanh điều hướng.
// Trong file AppServiceProvider.php, phương thức boot()
view()->share('siteName', 'Laravel Academy');
view()->share('siteUrl', 'https://xueyuanjun.com');
Các biến $siteName và $siteUrl sẽ có sẵn trong mọi view.
Tổng quan về Blade Engine
Blade là một công cụ tạo mẫu đơn giản nhưng mạnh mẽ. Nó cho phép kết hợp mã HTML với các cú pháp đặc biệt để tạo các tệp view động. Blade cung cấp các tính năng sau:
{{ $variable }}: Hiển thị biến PHP đã được thoát HTML để tránh tấn công XSS.{!! $variable !!}: Hiển thị biến PHP dưới dạng HTML thô, không thoát.- Các chỉ thị bắt đầu bằng
@: Dùng cho các cấu trúc điều khiển, kế thừa, bao gồm, v.v.
Các tệp .blade.php được biên dịch thành mã PHP thuần túy và lưu vào bộ nhớ cache tại storage/framework/views để tối ưu hiệu suất.
Hiển thị Dữ liệu
Cú pháp {{ }} tự động thoát các ký tự HTML bằng cách sử dụng hàm htmlentities(), đảm bảo an toàn cho ứng dụng.
// Tương đương với
{{ $variable }}
// Hiển thị HTML thô
{!! $htmlContent !!}
Để tránh việc Blade Engine cố gắng biên dịch các biến JavaScript được định nghĩa bằng cú pháp tương tự, hãy thêm ký tự @ phía trước:
// Dữ liệu PHP sẽ được Blade biên dịch
{{ $phpData }}
// Blade sẽ bỏ qua và loại bỏ '@', giữ lại cấu trúc {{ $vueData }} cho JavaScript
@{{ $vueData }}
Để tạo comment trong Blade, sử dụng cú pháp:
{{-- Đây là một comment trong Blade --}}
Cấu trúc Điều khiển
Câu lệnh Điều kiện
Blade cung cấp các chỉ thị tương tự như PHP:
@if,@elseif,@else,@endif@unless: Tương đương vớiif (!$condition)@isset,@empty: Tương đương vớiisset()vàempty()@switch,@case,@break,@default,@endswitch
@if (count($students) === 1)
Chỉ có một sinh viên trong sân.
@elseif (count($students) === 0)
Không có sinh viên nào trong sân.
@else
Có {{ count($students) }} sinh viên trong sân.
@endif
@unless ($user->hasPaid())
Người dùng chưa thanh toán.
@endunless
Cấu trúc Lặp
Blade hỗ trợ các chỉ thị lặp tương tự PHP:
@for,@foreach,@while@forelse: Kết hợp@foreachvới một block@emptycho trường hợp không có dữ liệu.
@for ($i = 0; $i < 10; $i++)
Số hiện tại là {{ $i }}
@endfor
@foreach ($users as $user)
{{ $user->name }}
@endforeach
@forelse ($products as $product)
{{ $product->name }}
@empty
Không tìm thấy sản phẩm nào.
@endforelse
Biến $loop trong Vòng lặp
Trong các vòng lặp @foreach và @forelse, biến $loop cung cấp thông tin hữu ích như chỉ số hiện tại ($loop->iteration), có phải là lần lặp đầu tiên không ($loop->first), có phải là lần lặp cuối cùng không ($loop->last), cấp độ lồng nhau ($loop->depth) và thông tin về vòng lặp cha ($loop->parent).
<ul>
@foreach ($pages as $page)
<li>{{ $loop->iteration }}: {{ $page->title }}</li>
@endforeach
</ul>
Kế thừa Template
Blade cho phép bạn định nghĩa các layout cơ sở và kế thừa chúng trong các view con.
Định nghĩa Slot với @yield và @section
Trong tệp layout, bạn định nghĩa các vùng nội dung có thể được ghi đè bởi các view con.
<!-- resources/views/layouts/master.blade.php -->
<html>
<head>
<title>Laravel Academy | @yield('title', 'Trang chủ')</title>
</head>
<body>
<div class="container">
@yield('content')
</div>
@section('footerScripts')
<script src="{{ asset('js/app.js') }}"></script>
@show
</body>
</html>
@yield('section_name', 'default_value'): Đặt một vùng nội dung.@section('section_name') ... @show: Đặt một vùng nội dung có thể kế thừa và ghi đè. Nội dung mặc định có thể được truy cập bằng@parent.
Kế thừa và Ghi đè với @extends và @section
Trong view con, bạn sử dụng @extends để chỉ định layout cha và @section để cung cấp nội dung cho các slot.
<!-- resources/views/dashboard.blade.php -->
@extends('layouts.master')
@section('title', 'Bảng điều khiển')
@section('content')
Chào mừng đến với Bảng điều khiển!
@endsection
@section('footerScripts')
@parent
<script src="{{ asset('js/dashboard.js') }}"></script>
@endsection
Bao gồm các View con với @include
Chỉ thị @include cho phép bạn nhúng nội dung của một view khác vào view hiện tại.
<!-- resources/views/sign-up-button.blade.php -->
<a class="button">{{ $text }}</a>
<!-- resources/views/home.blade.php -->
@include('sign-up-button', ['text' => 'Đăng ký ngay'])
Đặt dữ liệu View trước với View Composer
View Composer là các hàm callback được thực thi khi một view cụ thể được render. Chúng hữu ích để tải dữ liệu chung mà không cần lặp lại việc truyền dữ liệu trong mỗi route hoặc controller.
// Trong AppServiceProvider.php, phương thức boot()
use App\Models\Post; // Giả sử bạn có model Post
view()->composer('partials.sidebar', function ($view) {
$view->with('latestPosts', Post::orderBy('created_at', 'desc')->take(5)->get());
});
Biến $latestPosts sẽ có sẵn trong view partials.sidebar.
Bạn cũng có thể sử dụng các lớp tùy chỉnh cho View Composer để tổ chức mã tốt hơn.
with('latestPosts', Post::orderBy('created_at', 'desc')->take(5)->get());
}
}
// Trong AppServiceProvider.php, phương thức boot()
use App\Http\ViewComposers\SidebarComposer;
view()->composer('partials.sidebar', SidebarComposer::class);
Inject Services vào View
Chỉ thị @inject cho phép bạn đưa các service từ Service Container vào view.
@inject('analytics', 'App\Services\AnalyticsService')
<div>
Số dư: {{ $analytics->getBalance() }}
</div>
Lưu ý: Việc inject service trực tiếp vào view không được khuyến khích vì nó có thể làm mờ ranh giới giữa logic nghiệp vụ và lớp trình bày.
Tạo Chỉ thị Blade Tùy chỉnh
Bạn có thể định nghĩa các chỉ thị Blade của riêng mình để thực hiện các tác vụ lặp đi lặp lại.
// Trong AppServiceProvider.php, phương thức boot()
use Illuminate\Support\Facades\Blade;
Blade::directive('formatDateTime', function ($expression) {
return "format('Y-m-d H:i:s'); ?>";
});
// Sử dụng trong view:
@formatDateTime($timestamp)
Sau khi thêm hoặc sửa đổi chỉ thị Blade, hãy xóa bộ nhớ cache của view bằng lệnh php artisan view:clear.