Nhiệm vụ của View là nhận dữ liệu từ Controller và sau đó dựa vào layout của giao diện nó sẽ xử lý dữ liệu theo yêu cầu. Mặc định các view sẽ được đặt trong thư mục resources/views
. Nếu như bạn muốn thay đổi thư mục bạn có thể vào config/view.php
thay đổi lại giá trị của paths
.
Mặc định laravel hỗ trợ view file có đuôi là .html
, .php
, .css
, .blade.php
. Nếu trong thư mục có cùng các view trùng tên thì laravel sẽ ưu tiên theo thứ tự như sau: .blade.php
, .php
, .css
, .html
.
1. Render View
Tạo view có tên là demo.blade.php
với nội dung như sau:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Demo View</title>
</head>
<body class="antialiased">
<h2>Trang demo View trong Laravel</h2>
</body>
</html>
Để render view trong Laravel các bạn có thể sử dụng hàm view()
hoặc View::make()
với cú pháp sau:
view($view, $data);
// Hoặc
use \Illuminate\Support\Facades\View;
View::make($view, $data);
Trong đó:
– $view
là path đến view (tính từ thư mục views
).
– $data
là mảng data bạn muốn truyền vào trong view. Tham số này có thể bỏ trống.
Ví dụ: Mình sẽ render view demo.blade.php
trong ví dụ trên
/* File routes/web.php */
Route::get('demoview', function() {
return view('demo');
})->name('demoview');
Kết quả
Truyền data vào View
File demo.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Demo View</title>
</head>
<body class="antialiased">
<h2>Trang demo View trong Laravel</h2>
<div>
<p><?=$name?></p>
<p><?=$age?></p>
</div>
</body>
</html>
Hoặc
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Demo View</title>
</head>
<body class="antialiased">
<h2>Trang demo View trong Laravel</h2>
<div>
<p>{{$name}}</p>
<p>{{$age}}</p>
</div>
</body>
</html>
File routes/web.php
Route::get('demoview', function() {
return view('demo', ['name'=>'John', 'age'=>30]);
})->name('demoview');
Kết quả
Nếu trong trường hợp view của bạn nằm trong một thư mục con trong resources/views
thì bạn có thể sử dụng dấu .
để đại diện cho kí tự /
.
Ví dụ: Nếu file demo.blade.php
bên trên nằm trong thư mục con test
của views
File routes/web.php
Route::get('demoview', function() {
return view('test.demo', ['name'=>'John', 'age'=>30]);
})->name('demoview');
2. View first
Trong một số trường hợp bạn muốn render ra view tồn tại đầu tiên trong danh sách view thì bạn có thể sử dụng phương thức first trong View
object với cú pháp như sau:
use Illuminate\Support\Facades\View;
View::first($views, $data);
Trong đó:
$views
là mảng path đến view (tính từ thư mục views).
$data
là mảng data bạn muốn truyền vào trong view. Tham số này có thể bỏ trống.
File routes/web.php
return View::first(['no_exist', 'demo']);
Ở đây global helper function view sẽ trả về một object nên ta có thể tham chiếu tiếp đến method first. Laravel sẽ lần lượt kiểm tra các view này từ trái qua phải, nếu view nào không tồn tại thì nó sẽ bỏ qua. view no_exist
không tồn tại nên sau khi chạy đường dẫn http://localhost:8000
thì chúng ta nhận được view demo
3. Kiểm tra View tồn tại
File routes/web.php
Route::get('view_exist', function () {
if (View::exists('demo')) {
return 'view demo tồn tại';
}
else {
return 'view demo không tồn tại';
}
})->name('view_exist');
Kết quả
4. Truyền data cho tất cả view
Để truyền dữ liệu cho tất cả các view có trong source code với method share
trong view facade. Phương thức này sẽ được khi báo ở AppServiceProvider
tại method boot
trong thư mục Providers:
public function boot()
{
View::share('key', 'value');
}
Bây giờ tất cả các file view đều có thể gọi $key
với giá trị là value
Ví dụ
public function boot()
{
View::share('laravelTitle', 'Học Laravel');
}
5. View composer
View composer là một class
hoặc một callback
nó sẽ được gọi khi view render
. Nếu bạn muốn đưa data vào view khi render thì View composer cũng là một giải pháp dành cho bạn.
Trong một số trường hợp nhiều view cần dùng chung một đoạn logic (nhưng không phải tất cả) và truyền vào view thì bạn nên sử dụng view composer
cho code đỡ bị lặp lại.
Bạn cần đăng kí view composer
vào trong provider
Có hai cách để khai báo view composer
đó là dùng closure
hoặc là class
Đối với view composer
dùng closure
thì bạn chỉ việc khai báo theo cú pháp sau:
View::composer($views, function ($view) {
// Code
});
Trong đó: $view
là view bạn muốn tác động. Nếu bạn muốn tác động đến nhiều view bạn có thể truyền vào một mảng và nếu bạn muốn tác động hết thì chỉ cần khai báo $view = '*'
.
Ví dụ: thêm $note
vào trong view demo
. Sử dụng view composer
File routes/web.php
View::composer('home', function ($view) {
$view->with('note', 'View composer');
});
File demo.blade.php
ở mục 1 phía trên viết lại như sau:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Demo View</title>
</head>
<body class="antialiased">
<h2>Trang demo View trong Laravel</h2>
<div>
<p><?=$name?></p>
<p><?=$age?></p>
<p><?=$note?></p>
</div>
</body>
</html>
Kết quả
Trong view demo chỉ cần gọi tên biến $note
đã được truyền vào từ view composer
Đối với view composer
dùng class thì bạn chỉ việc khai báo theo cú pháp sau:
View::composer($views, $className);
Trong đó:
$view
thì tương tự như đối với view composer closure.
$className
là tên của class chưa logic composer. Class composer này bắt buộc phải có method compose
có visibility là public
và nhận tham số truyền vào là một View
object.
Đăng ký view composer
Trong service container như là một service provider. Đầu tiên ta khởi tạo provider ViewComposerProvider
với lệnh Artisan sau:
php artisan make:provider ViewComposerProvider
Liệt kê ViewComposerProvider
vừa khởi tạo trong mảng providers
ở config/app.php
'providers' => [
// ..
App\Providers\ViewComposerProvider::class,
],
Tiếp theo mở file app/Providers/ViewComposerProvider.php
lên và thay đổi nội dung nó thành:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
//Thêm 2 dòng này
use Illuminate\Support\Facades\View;
use App\Http\View\Composers\ProfileComposer;
class ViewComposerProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
// Registering composer with Class
View::composer(
'profile', ProfileComposer::class
);
}
}
Mặc định thì Laravel không tạo thư mục chứa các file composer mà để chúng ta tự tổ chức. Bạn có thể tạo cấp thư mục như sau để chứa các composer:
File app/Http/View/Composers/ProfileComposer.php
<?php
namespace App\Http\View\Composers;
use Illuminate\View\View;
class ProfileComposer {
public function compose(View $view) {
$view->with('title', 'Học Laravel 8');
}
}
?>
Bắt buộc trong file composer phải định nghĩa method compose
và inject cho nó class Illuminate\View\View
, từ đó ta mới có thể dùng phương thức with
để truyền dữ liệu cho view
đã đăng ký ở ViewComposerProvider.
Cách hoạt động của hình thức đăng ký composer với class
đó là khi một view tương ứng chuẩn bị render thì sẽ gọi phương thức compose
của class đã đăng ký chung với view đó. Trong trường hợp trên thì khi view profile
sắp render thì ProfileComposer@compose
sẽ được thực thi để truyền các dữ liệu
File resources/view/profile.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>View Composer</title>
</head>
<body class="antialiased">
<h2>View Composer trong Laravel</h2>
<div>
<p><?=$title?></p>
</div>
</body>
</html>
Tiếp đó là đăng ký một route để render view profile
:
File routes/web.php
Route::get('/profile', function () {
return view('profile');
});
Kết quả
HI