View Laravel

Trong các bài viết trước chúng ta đã được tìm hiểu về cấu trúc cũng như route trong Laravel rồi đúng không nào. Tiếp theo trong bài viết này chúng mình sẽ tiếp tục tìm hiểu về View trong Laravel một thành phần khá là quan trọng trong mô hình MVC framework

1. Khởi tạo view (Creating view)

Không giống với phần lớn component, view hơi nhọ khi nó không được tạo bằng lệnh Artisan mà chỉ có thể thực hiện theo cách thủ công. Toàn bộ các viewer sẽ nằm trong thư mục resources/views.

Chúng ta sẽ có hai loại file view:

  • Template thuần: có nghĩa trong đó chỉ chứa các mã PHP, HTML, CSS, Javascript... thông thường, đuôi mở rộng file là .php
  • Blade template: đây là một view engine của Laravel, chúng ta sẽ sử dụng những cú pháp riêng biệt để có thể làm code nhanh hơn, ngắn gọn hơn rất nhiều, đuôi mở rộng file là .blade.php.

Nhưng trong bài này chúng ta chỉ sử dụng template thuần , ở trong bài sau chúng ta sẽ nói về blade template.

Ví dụ giờ mình sẽ tạo một file view begin.php với nội dung sau:

resources/views/begin.php

<h1>Xin chao cac ban</h1>

Để có thể xuất view này cho client, các bạn khai báo route như sau:

route/web.php

Route::get('/batdau', function () {
    return view('begin');
});

Chúng ta sử dụng một global helper function view để có thể trả về một view nào đó với tham số là tên của view (không lấy đuôi mở rộng).

Truy cập đường dẫn http://localhost:8000/batdau chắc chắn bạn sẽ nhận được kết quả:

View trong Laravel có thể phân chia cấp thư mục để dễ dàng quản lý. Chẳng hạn ứng dụng của bạn có client-side và admin-side, nên bạn muốn các view của admin-side sẽ nằm ở trong một thư mục resources/views/admin.

resources/
├── views/
|   ├── admin/
|   |   |   setting.php 
|   |   begin.php

Bây giờ chúng ta làm thể nào để truy cập view admin/setting.php? Các bạn hãy quan sát đoạn code sau:

Route::get('/admin/setting', function() {
    return view('admin.setting');
});

Vẫn là hàm view quen thuộc, nhưng lần tham số truyền vào có chút đặc biệt, đó là có thêm dấu chấm (.). Với dấu này, Laravel sẽ hiểu là chúng ta đang đi vào sub-directory admin/setting.

2. Truyền dữ liệu cho view (Passing data to view)

Ta có thể truyền dữ liệu cho view thông qua tham số thứ hai của hàm view.

route/web.php

Route::get('/xinchao', function () {
    return view('xinchao', ['name' => 'Pham Nhan']);
});

Để nhận giá trị name này thì tại view xinchao ta chỉ cần khai báo $name.

resources/views/xinchao.php

<h2>Welcome, <?php echo $name; ?></h2>

Để lấy dữ liệu được truyền tới view, ta chỉ cần khai báo biến có tên trùng với tên key trong mảng dữ liệu.

Kiểm tra kết quả http://localhost:8000/xinchao


Bạn có thể sử dụng method with để truyền dữ liệu thay cho cách trên:

Route::get('/xinchao', function () {
    return view('xinchao')->with('name', 'Pham Nhan');
});

Phương thức with này có thể truyền theo 2 cách:

  • Nếu bạn chỉ truyền một key thì có thể sử dụng cú pháp with($key, $value).
  • Nếu bạn truyền một mảng dữ liệu thì sử dụng cú pháp with($data).

Ngoài ra, chúng ta có thể 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:

app/Providers/AppServiceProvider.php

public function boot()
{
    View::share('key', 'value');
}

Như thế này thì tất cả các file view đều có thể gọi $key với giá trị là value.

4. View composer

View composer là các callback hoặc là các phương thức được gọi lại khi một view sắp sửa xuất ra (render). Nếu bạn có một dữ liệu nào đó mà bạn muốn truyền vào một view khi nó chuẩn bị render thì view composer sẽ giúp bạn thực hiện công việc truyền dữ liệu cho view một cách đầy khoa học (khả năng chức logic, tách rời, dễ kiểm soát).

4.1 Đăng ký view composer (Registering view composer)

Trước hết chúng ta sẽ đă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:

Trên Cmder gõ

php artisan make:provider ViewComposerProvider

Nên nhớ hãy liệt kệ ViewComposerProvider vừa khởi tạo trong mảng providers ở config/app.php.

Tìm đoạn 'providers' ... App rồi thêm vào code

'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\Facades\View;
use Illuminate\Support\ServiceProvider;
class ViewComposerProvider extends ServiceProvider
{
    public function register()
    {
        //
    }
    public function boot()
    {
        // Registering composer with Class
        View::composer(
            'profile', 'App\Http\View\Composers\ProfileComposer'
        );
        // Registering composer with Closure
        View::composer('dashboard', function ($view) {
            //
        });
    }
}

Trước tiên, chúng ta sẽ phân tích từ đoạn code một.

Ta đã use View facade vào class này để có thể thực hiện composer. Nếu việc binding được viết ở method register thì composer lại được viết ở boot.

Bây giờ hãy quan sát đoạn code trong method boot sẽ thấy có hai cách để đăng ký view composer.

4.1.1 Đăng ký composer với class (Registering composer with class)

Đăng ký composer với class

  • Tham số thứ nhất đó chính là tên của view cần truyền dữ liệu.
  • Tham số thứ hai sẽ chứa namespace class thực hiện việc compose

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:

app/
├── Http/
|   ├── View/
|   |   ├── Composers/
|   |   |   |   ProfileComposer.php 

Trong file ProfileComposer.php chúng ta sẽ code như thế này:

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('name', 'Pham Nhan');
    }
}

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.

Bây giờ chúng ta tạo thử view profile và xem nó hoạt động ra sao.

resources/views/profile.php

<h1>Profile <?php echo $name ?></h1>

Tiếp đó là đăng ký một route để render view profile:

Route/web.php

Route::get('/profile', function () {
    return view('profile');
});

Như bạn thấy thì mình không truyền bất cứ dữ liệu nào vào hàm view cả, bây giờ thử nạp server và xem kết quả.

Lưu ý: Tất cả các file composer đều resolve thông qua service container, vì vậy ta có thể type-hint bất kỳ dependency class nào cần thiết trong phương thức __construct.

4.1.2  Đăng ký composer với closure (Registering composer with closure)

Cách đăng ký này tương đối ngắng gọn hơn so với đăng ký theo class vì chúng ta không cần phải khởi tạo file composer mà chỉ cần truyền dữ liệu trực tiếp thông qua Closure là được.

app/Providers/ViewComposerProvider.php

View::composer('dashboard', function ($view) {
    $view->with('name', 'Pham Nhan');
});

Ở đây chúng ta đã truyền dữ liệu cho view dashboard thông qua $view của Closure.

Bây giờ hãy thử tạo view dashboard với nội dung:

resources/views/dashboard.php

<h1>Welcome, <?php echo $name; ?></h1>

Tiếp đó đương nhiên phải đăng ký route:

routes/web.php

Route::get('/', function () {
    return view('dashboard');
});

Bước tiếp theo là nạp server và kiểm chứng thôi.

Chọn cách nào để đăng ký view composer hợp lý.

Thì đây là ý kiến riêng của mình, đối với các view mà sẽ nhận dữ liệu từ database thì nên đăng ký composer theo class để dễ dàng type-hint các dependency class cần thiết cho việc lấy dữ liệu. Còn nếu chỉ là truyền một số dữ liệu đơn giản, thao tác nhanh thì nên cân nhắc để chọn cách đăng ký composer theo closure để giảm tốn thời gian, rườm rà.

Bạn có thể đăng ký một view composer cho nhiều view khác nhau bằng cách chuyển tham số thứ nhất về dạng mảng và liệt kê các view cần thiết.

View::composer(
    ['profile', 'dashboard'],
    'App\Http\View\Composers\ProfileComposer'
);

Trong trường hợp bạn muốn tất cả các view đều được truyền một dữ liệu chung thì bạn có thể sử dụng ký tự * để thay thế tên view, framework sẽ hiểu là bạn đã chọn tất cả các view đang có trong source code.

View::composer('*', function ($view) {
    //
});

5. View creator

Về hình thức thì view creator chẳng khác gì mấy so vớ view composer, tuy nhiên về cách hoạt động thì có sự khác biệt về trình tự. Nếu composer thực thi khi view sắp sửa render thì creator lại thực thi khi vừa khởi tạo view thay vì chờ nó chuẩn bị render.

6. Lời kết:

Vậy là chúng ta đã tìm hiểu xong về view trong Laravel rồi đấy. Vì chỉ là 1 bài học thế nên lượng kiến thức hay ví dụ chúng mình đưa ra còn ít các bạn thông cảm nhé. Cảm ơn các bạn đã theo dõi!

Bình luận