Laravel 8 có gì mới - Những cải tiến quan trọng nhất

Laravel 8 tiếp tục có những cải tiến từ phiên bản 7.x, bằng việc ra mắt Laravel Jetstream, lớp model factory, gộp migrations, cải thiện rate limit, queue, artisan serve, event listener, blade component động, Tailwind, time testing helper, và fix một vài bug khác…

Laravel Jetstream

Jetstream là một loại mì ăn liền mới của Laravel, là bản cải tiến của php artisan make:auth hay laravel new projectName --auth. Khi bạn tạo một project Laravel mới, nếu muốn có sẵn một set những thứ như login, register, email verification, 2-factor authentication, quản lý session, hỗ trợ sẵn API bằng Laravel Sanctum và set up sẵn SaaS thì không còn gì dễ hơn việc chạy câu lệnh như sau:


$ laravel new projectName --jet

Sau khi chạy câu lệnh trên, terminal sẽ hỏi bạn chọn Livewire hay Inertia thì chào mừng bạn đến với một tập những thứ mới hơn cả chữ mới.

  • Laravel Livewire là một thư viện để làm giao diện cho Laravel dùng Blade Engine. Đây là sự lựa chọn không thể phù hợp hơn nếu bạn thích làm giao diện vừa động vừa ngầu nhưng bạn lại không thích dùng mấy cái Javascript Framework anh em bạn dì với Laravel ví dụ như Vuejs.

  • Inertial.js thì ngược lại. Nó dành cho những bạn trẻ đam mê với việc làm giao diện bằng Javascript, cụ thể là Vuejs. Tuy nhiên, nó lại không dùng Vue router để điều hướng mà sẽ dùng Laravel router. Điều này sẽ giảm bớt stress cho những ai hay bị nhức đầu ở mấy cái routing của teammate, lúc thì routing bằng Laravel, lúc thì routing bằng Javascript.

Sau khi bạn đã quyết định mình sẽ làm giao diện bằng Blade hay bằng Vuejs, bước tiếp theo bạn sẽ được lựa chọn cho mình cái trang web mà mình đang định làm này có phải SaaS không, lúc này hay nghĩ xem mình có phải quản lý teams không, một user có được ở trong nhiều team, nhiều workspace không các thứ các thứ… Nếu có thì gõ chữ Yes, còn mặc định chọn No, nên mình cứ bấm enter cho nhanh.

Models Directory

Ơn giời nó đây rồi, qua 7 phiên bản Laravel mới có một cái khiến cho framework đúng y như sách giáo khoa, rằng là mô hình MVC các kiểu. Founder của Laravel bảo là ông ấy đã quá mệt nên thôi chiều lòng cư dân mạng, tạo cái folder Models cho tụi nó đỡ kêu và thế là có rồi đây, thỏa mong ước bấy lâu nay.

Model Factory Classes

Một tính năng cũng khá được mong chờ rằng nó phải được cải thiện, đó là Model Factory. Trước đây cái factory cho model nó như này:


<?php
use App\User;
use Faker\Generator as Faker;
use Illuminate\Support\Str;

$factory->define(User::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'email_verified_at' => now(),
        'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
        'remember_token' => Str::random(10),
    ];

});

Nhìn khá là bực á, vì thêm các state cho model phức tạp cực kỳ. Nhưng nay thời thế đã khác, chiếc factory ngày nào nay đã được nâng đời lên thành một class hoàn chỉnh như sau:


<?php

namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class UserFactory extends Factory
{
    protected $model = User::class;

    public function definition()
    {
        return [
            'name' => $this->faker->name,
            'email' => $this->faker->unique()->safeEmail,
            'email_verified_at' => now(),
            'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
            'remember_token' => Str::random(10),
        ];
    }
}

Nhìn code thôi đã thấy sang rồi. Cách dùng cũng dễ dàng hơn ngày trước rất nhiều.


use App\Models\User;

User::factory()->count(50)->create();

Do model factory nay đã là một PHP class, nên các state cũng được viết bằng các phương thức của lớp như bình thường. Nếu như ngày trước ta định nghĩa state cho factory như sau:


$factory->state(App\User::class, 'inactive', [
    'account_status' => 'inactive',
]);

thì nay ta sẽ định nghĩa state như này:


public function inactive()
{
    return $this->state([
        'account_status' => 'inactive',
    ]);
}

Đây sẽ là cách dùng state sau khi đã được khai báo:


use App\Models\User;

User::factory()->count(5)->inactive()->create();

Migration squashing

Nếu ngày trước, khi bắt đầu join vào một dự án đã xây một thời gian, bạn sẽ bị choáng ngợp trước hàng chục, thậm chí hàng trăm file migration. Gõ php artisan migrate mà có cảm giác như mình đang đóng phim hành động vậy. Do các file migration không được phép sửa khi đã commit, nên chúng ta có một công cụ dùng để gom hết đám file migration lại thành một file như sau:


$ php artisan schema:dump

// gộp các file migration lại thành file schema rồi xóa hết các file migration đã được gộp
$ php artisan schema:dump --prune

Sau khi chạy các lệnh trên, Laravel sẽ viết một file schema vào thư mục database/schema. Từ giờ, khi bạn chạy php artisan migrate, Laravel sẽ chạy file schema trước, sau đó sẽ chạy những file migration mà không có trong schema.

Routing Namespace

Vẫn là một sự cải tiến thật sự cần thiết, khi mà trong file web.php, ta phải viết cái tên controller gồm một dãy dài namespace rồi đặt trong một cặp dấu nháy string thì việc dùng static attibute class để lấy đủ tên của controller sẽ đỡ gây nhầm lẫn hơn.

So sánh 2 cách viết route như sau:


Route::get('/users', 'UserController@index');


use App\Http\Controllers\UserController;

Route::get('/users', [UserController::class, 'index']);

thì rõ ràng cách viết thứ 2 nhìn tường minh hơn nhiều và tránh những lỗi gõ sai tên và đường dẫn tới controller.

Những chú ý trong lần cải tiến này, đó là mặc định namespace khai báo trong RouteServiceProvider sẽ là null. Còn ngày trước mặc định sẽ là App\Http\Controller. Vậy nên, ở cách viết mới, ta sẽ phải tự khai báo namespace rõ ràng trong routes mới sử dụng được.

Trên đây là những cải tiến mình đánh giá là quan trọng nhất, cơ bản nhất và cần phải nắm rõ nhất khi các bạn chuyển từ Laravel 5-6-7x sang Laravel 8. Sau bài viết này, mình sẽ giới thiệu với các bạn chi tiết hơn về Jetstream, Inertia, Livewire,… Cùng đón chờ bài viết sắp tới của mình nhé.