
Chào các bạn đồng nghiệp tương lai của ngành lập trình! Hôm nay, chúng ta sẽ cùng nhau mổ xẻ một khái niệm cực kỳ quan trọng, là "bộ mặt" của mọi ứng dụng web: View trong Laravel.
Hãy hình dung thế này: Nếu ứng dụng web của bạn là một nhà hàng, thì Laravel là toàn bộ hệ thống quản lý từ bếp núc, kho hàng cho đến phục vụ. Trong đó:
- Model chính là kho nguyên liệu và công thức nấu ăn (dữ liệu và logic nghiệp vụ).
- Controller là người quản lý nhà hàng, nhận order từ khách, điều phối bếp, và đưa món ăn ra.
- Còn View? View chính là không gian ăn uống được trang trí đẹp đẽ, là cái menu thiết kế tinh xảo, là cái đĩa bạn dùng để bày biện món ăn – tóm lại, nó là tất cả những gì thực khách (người dùng) nhìn thấy và tương tác trực tiếp.
1. View Là Gì và Để Làm Gì?
Trong kiến trúc MVC (Model-View-Controller) mà Laravel theo đuổi, View là lớp chịu trách nhiệm hiển thị dữ liệu cho người dùng. Nó không hề quan tâm đến việc dữ liệu đến từ đâu, được xử lý thế nào. Nhiệm vụ duy nhất của nó là nhận dữ liệu từ Controller và trình bày nó một cách trực quan, dễ hiểu trên trình duyệt.
Mục đích cốt lõi:
- Tách biệt rạch ròi: Giúp tách biệt logic hiển thị (HTML, CSS, JavaScript) khỏi logic nghiệp vụ của ứng dụng. Điều này giống như việc đầu bếp không cần phải lo trang trí bàn ăn, và người phục vụ không cần biết công thức nấu ăn vậy.
- Dễ bảo trì và phát triển: Khi code được tách lớp rõ ràng, việc sửa lỗi hay thêm tính năng mới trở nên dễ dàng hơn rất nhiều. Bạn muốn thay đổi giao diện? Chỉ cần sửa file View. Bạn muốn thay đổi cách xử lý dữ liệu? Sửa Controller hoặc Model.
- Tái sử dụng: Với công cụ templating mạnh mẽ của Laravel là Blade, chúng ta có thể tạo ra các layout chung, các thành phần giao diện nhỏ có thể tái sử dụng ở nhiều nơi, tiết kiệm thời gian và đảm bảo tính nhất quán.

2. Code Ví Dụ Minh Hoạ Rõ Ràng, Ngầu
Laravel sử dụng Blade templating engine cho các View của mình. Đây không phải là HTML thuần túy, mà là một siêu tập hợp của HTML, cho phép chúng ta viết code PHP một cách ngắn gọn, dễ đọc hơn ngay trong file HTML. Các file Blade có đuôi là .blade.php (ví dụ: welcome.blade.php).
Ví dụ 1: View Cơ Bản - "Xin Chào" Đơn Giản
Hãy tạo một file View và hiển thị nó.
Bước 1: Tạo file View
Trong thư mục resources/views, bạn tạo một file mới tên là hello.blade.php với nội dung sau:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chào Mừng Laravel</title>
</head>
<body>
<h1>Chào mừng đến với thế giới View của Laravel!</h1>
<p>Đây là trang đầu tiên của bạn.</p>
</body>
</html>
Bước 2: Định tuyến (Route) để hiển thị View
Mở file routes/web.php và thêm đoạn code sau:
use Illuminate\Support\Facades\Route;
Route::get('/chao-ban', function () {
return view('hello'); // 'hello' tương ứng với file hello.blade.php
});
Bây giờ, khi bạn truy cập http://your-app.test/chao-ban trên trình duyệt, bạn sẽ thấy nội dung của file hello.blade.php được hiển thị. Đơn giản như đang giỡn!
Ví dụ 2: Truyền Dữ Liệu Từ Controller Sang View
View thì đẹp đấy, nhưng nó cần "thức ăn" (dữ liệu) để trình bày chứ! Controller sẽ là người cung cấp thức ăn đó.
Bước 1: Tạo Controller (nếu chưa có) Bạn có thể tạo nhanh bằng Artisan:
php artisan make:controller PostController
Bước 2: Cập nhật Controller
Mở file app/Http/Controllers/PostController.php và thêm một phương thức index như sau:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index()
{
$posts = [
(object)['id' => 1, 'title' => 'Cà Phê Code: Nơi Ý Tưởng Nảy Mầm', 'author' => 'Lão Giảng Viên'],
(object)['id' => 2, 'title' => 'Blade: Vũ Khí Bí Mật Của Laravel View', 'author' => 'Lão Giảng Viên'],
(object)['id' => 3, 'title' => 'Tối Ưu Hóa Query Database Với Eloquent', 'author' => 'Mentor Code'],
];
// Truyền biến 'posts' sang View
return view('posts.index', ['posts' => $posts, 'pageTitle' => 'Danh Sách Bài Viết Cực Chất']);
}
}
Ở đây, chúng ta tạo một mảng $posts (coi như dữ liệu từ database) và một $pageTitle. Phương thức view() nhận hai tham số: tên view (posts.index nghĩa là file index.blade.php trong thư mục resources/views/posts/) và một mảng các biến mà bạn muốn truyền sang view.
Bước 3: Tạo View để hiển thị dữ liệu
Tạo thư mục posts trong resources/views, sau đó tạo file index.blade.php trong đó:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ $pageTitle ?? 'Mặc định' }}</title> {{-- Blade tự động thoát HTML để tránh XSS --}}
</head>
<body>
<h1>{{ $pageTitle }}</h1>
@if (count($posts) > 0)
<ul>
@foreach ($posts as $post)
<li>
<h3>{{ $post->title }}</h3>
<p>Tác giả: {{ $post->author }}</p>
<a href="/posts/{{ $post->id }}">Đọc thêm</a>
</li>
@endforeach
</ul>
@else
<p>Chưa có bài viết nào cả. Đi viết bài đi!</p>
@endif
</body>
</html>
Chú ý cách chúng ta dùng {{ $variable }} để in biến ra. Blade sẽ tự động thoát HTML để bảo vệ ứng dụng khỏi các cuộc tấn công XSS (Cross-Site Scripting).
Và đây là sức mạnh của Blade:
@if,@else,@endif: Các cấu trúc điều kiện quen thuộc.@foreach,@endforeach: Vòng lặp để duyệt qua danh sách.{{ $pageTitle ?? 'Mặc định' }}: Toán tử null coalescing của PHP 7, Blade cũng hỗ trợ, giúp in ra giá trị nếu biến tồn tại, không thì dùng giá trị mặc định.
Bước 4: Định tuyến cho Controller
Mở routes/web.php và thêm:
use App\Http\Controllers\PostController;
Route::get('/posts', [PostController::class, 'index']);
Truy cập http://your-app.test/posts, bạn sẽ thấy danh sách bài viết được hiển thị. Tuyệt vời phải không?
Ví dụ 3: Layouts và Sections - Kiến Trúc UI Vững Chắc
Viết HTML lặp đi lặp lại cho header, footer, sidebar ở mỗi trang là một cơn ác mộng. Blade giải quyết vấn đề này bằng Layouts và Sections. Hãy tưởng tượng bạn có một khuôn mẫu nhà hàng chung (layout), sau đó mỗi món ăn (page) chỉ cần tập trung vào phần nội dung chính của nó.
Bước 1: Tạo Layout Chính
Trong resources/views/layouts, tạo file app.blade.php (hoặc tên gì bạn thích, miễn là dễ hiểu):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ứng Dụng Cực Chất - @yield('title')</title> {{-- 'title' là tên của section --}}
<link rel="stylesheet" href="/css/app.css"> {{-- Giả định bạn có file CSS này --}}
@yield('styles') {{-- Dùng cho các CSS riêng của từng trang --}}
</head>
<body>
<header>
<nav>
<a href="/">Trang Chủ</a> |
<a href="/posts">Bài Viết</a> |
<a href="/about">Về Chúng Tôi</a>
</nav>
</header>
<main>
@yield('content') {{-- Đây là nơi nội dung chính của từng trang sẽ được inject vào --}}
</main>
<footer>
<p>© {{ date('Y') }} Ứng Dụng Cực Chất Của Lão Giảng Viên. Tất cả bản quyền được bảo lưu.</p>
</footer>
<script src="/js/app.js"></script> {{-- Giả định bạn có file JS này --}}
@yield('scripts') {{-- Dùng cho các JS riêng của từng trang --}}
</body>
</html>
@yield('tên_section') là "lỗ hổng" mà các view con có thể "đổ" nội dung vào.
Bước 2: Cập nhật View con để sử dụng Layout
Cập nhật file resources/views/posts/index.blade.php của chúng ta:
@extends('layouts.app') {{-- Kế thừa layout app.blade.php --}}
@section('title', 'Danh Sách Bài Viết Cực Chất') {{-- Điền nội dung vào section 'title' --}}
@section('styles')
<style>
ul { list-style: none; padding: 0; }
li { margin-bottom: 20px; border-bottom: 1px solid #eee; padding-bottom: 15px; }
h3 { color: #333; }
a { color: #007bff; text-decoration: none; }
a:hover { text-decoration: underline; }
</style>
@endsection
@section('content') {{-- Điền nội dung chính vào section 'content' --}}
<h1>{{ $pageTitle }}</h1>
@if (count($posts) > 0)
<ul>
@foreach ($posts as $post)
<li>
<h3>{{ $post->title }}</h3>
<p>Tác giả: {{ $post->author }}</p>
<a href="/posts/{{ $post->id }}">Đọc thêm</a>
</li>
@endforeach
</ul>
@else
<p>Chưa có bài viết nào cả. Đi viết bài đi!</p>
@endif
@endsection
@section('scripts')
<script>
console.log("Trang danh sách bài viết đã được tải!");
</script>
@endsection
@extends('layouts.app'): Dòng thần chú này cho biết view hiện tại sẽ kế thừa từ layoutlayouts/app.blade.php.@section('tên_section') ... @endsection: Dùng để định nghĩa nội dung cho các section đã đượcyieldtrong layout cha. Nếu bạn chỉ muốn điền một chuỗi ngắn, có thể dùng@section('title', 'Chuỗi ngắn gọn').
Bây giờ, khi truy cập /posts, bạn sẽ thấy trang bài viết của mình có đầy đủ header, footer, và nội dung chính được đặt đúng chỗ. Sạch sẽ và chuyên nghiệp!
Ví dụ 4: Includes - Tái Sử Dụng Các Phần Nhỏ
Đôi khi, bạn có những phần nhỏ của giao diện được lặp đi lặp lại, nhưng không đủ lớn để làm một layout riêng. Ví dụ: một alert box, một form field chung, hay một phần tử sidebar nhỏ. Đó là lúc @include toả sáng.
Bước 1: Tạo một Partial View
Tạo file resources/views/partials/alert.blade.php:
<div class="alert alert-{{ $type ?? 'info' }}">
{{ $message ?? 'Đây là một thông báo chung.' }}
</div>
Ở đây, chúng ta dùng $type và $message như các biến có thể truyền vào.
Bước 2: Sử dụng Partial View trong View Chính
Cập nhật resources/views/posts/index.blade.php (hoặc bất kỳ view nào):
@extends('layouts.app')
@section('title', 'Danh Sách Bài Viết Cực Chất')
@section('content')
<h1>{{ $pageTitle }}</h1>
{{-- Sử dụng partial alert --}}
@include('partials.alert', ['type' => 'success', 'message' => 'Tải danh sách bài viết thành công!'])
@if (count($posts) > 0)
<ul>
@foreach ($posts as $post)
<li>
<h3>{{ $post->title }}</h3>
<p>Tác giả: {{ $post->author }}</p>
<a href="/posts/{{ $post->id }}">Đọc thêm</a>
</li>
@endforeach
</ul>
@else
@include('partials.alert', ['type' => 'warning', 'message' => 'Chưa có bài viết nào cả.'])
@endif
@endsection
Bạn có thể truyền dữ liệu cho @include tương tự như truyền dữ liệu cho view(). Các biến này chỉ có hiệu lực trong phạm vi của partial view đó.
3. Một Vài Mẹo (Best Practices) Để Ghi Nhớ Hoặc Dùng Thực Tế
- "View Chỉ Nên Loe Hoe Việc Hiển Thị": Đây là câu thần chú. View không phải là nơi để bạn thực hiện các phép tính phức tạp, truy vấn database, hay xử lý logic nghiệp vụ. Nếu bạn thấy mình viết
ifhayforeachquá dài dòng, hay gọi các phương thức phức tạp trong View, đó là dấu hiệu bạn đang làm sai. Hãy đưa logic đó về Controller hoặc thậm chí là Model/Service. View chỉ nên là "cái gương" phản chiếu dữ liệu đã được xử lý. - Tận Dụng Tối Đa Blade Layout Inheritance: Đây là tính năng mạnh mẽ nhất của Blade. Luôn luôn tạo một
layouts/app.blade.phphoặc tương tự để định nghĩa cấu trúc HTML chung cho toàn bộ ứng dụng. Sau đó, tất cả các view con chỉ cần@extendslayout này và điền nội dung vào các@sectiontương ứng. Điều này giúp code của bạn DRY (Don't Repeat Yourself) và dễ quản lý khi cần thay đổi giao diện toàn cục. - Sử Dụng
@includecho các "Component" nhỏ: Các thành phần UI nhỏ, có thể tái sử dụng như alert box, form field, pagination links, v.v., nên được đặt trong các partial view riêng (ví dụ:partials/_form_errors.blade.php). Điều này giúp mã nguồn của bạn gọn gàng và dễ bảo trì. - Đặt Tên View Rõ Ràng, Có Cấu Trúc Thư Mục:
resources/views/posts/index.blade.php(danh sách bài viết)resources/views/posts/show.blade.php(chi tiết bài viết)resources/views/users/profile.blade.php(trang hồ sơ người dùng) Cấu trúc này giúp bạn dễ dàng tìm kiếm và tổ chức các file view khi dự án lớn lên.
- Cẩn Thận với
{!! $variable !!}: Laravel tự động thoát HTML khi bạn dùng{{ $variable }}để chống XSS. Nếu bạn muốn hiển thị HTML "thô" (ví dụ, nội dung bài viết được nhập từ trình soạn thảo rich text), bạn phải dùng{!! $variable !!}. Nhưng hãy nhớ, chỉ làm điều này với dữ liệu mà bạn đã kiểm tra và làm sạch cẩn thận ở phía backend. Nếu không, bạn đang mở cửa cho hacker tấn công ứng dụng của mình. - Sử Dụng Blade Components (Laravel 7+): Đối với các thành phần UI phức tạp hơn, có logic riêng (ví dụ: một nút bấm tùy chỉnh, một thẻ sản phẩm), Blade Components là một giải pháp cực kỳ mạnh mẽ và thanh lịch. Nó cho phép bạn đóng gói HTML, CSS và thậm chí cả logic PHP nhỏ vào một "thẻ" duy nhất, dễ dàng tái sử dụng.
- Localization (@lang,
__): Khi ứng dụng của bạn cần hỗ trợ đa ngôn ngữ, hãy sử dụng@lang('messages.welcome')hoặc{{ __('messages.welcome') }}thay vì viết thẳng chuỗi text vào view. Điều này giúp việc dịch thuật trở nên dễ dàng hơn rất nhiều.
Nhớ nhé, View không chỉ là "mặt tiền" mà còn là "linh hồn" của trải nghiệm người dùng. Một View được thiết kế tốt, code sạch sẽ, sẽ mang lại ấn tượng mạnh mẽ cho cả người dùng lẫn các lập trình viên khác khi đọc code của bạn. Nắm vững View, bạn đã nắm được một nửa sức mạnh của Laravel rồi đó! Chúc các bạn code vui vẻ!
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é!