Laravel Tutorial

Bài 6: View Trong Laravel

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.phptrong 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 boottrong 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 $notevà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ả

 

1 Comment

Leave a Comment