Những tính năng mới trong Laravel 5.3
Đánh giá bài viết

Hội nghị Laracon US 2016 một trong những hội nghị lớn được mong chờ nhất trong năm 2016 đối với cộng đồng Laravel nói riêng và PHP nói chung đã được diễn ra (từ 27 đến 29-07-2016). Với mục tiêu chính là giới thiệu và released phiên bản Laravel 5.3.

Ở bài viết này chúng ta sẽ cùng nhau điểm qua những tính năng mới được giới thiệu trong Laravel 5.3:

  1. Giới thiệu Laravel Echo
  2. Biến $loop mới
  3. Thêm tham số mới cho hàm FirstOrCreate
  4. Global helper cache()
  5. Thêm phương thức truy vấn với JSON-column cho where() và update()
  6. Những thực thi nâng cao với Collection::where
  7. Validation kích thước ảnh
  8. Tùy biến templates phân trang
  9. Thay đổi route
  10. Giới thiệu Laravel Scout
  11. Giới thiệu Laravel Passport (updating)
  12. Elixir 6: webpack, rollup, scripts, and more (updating)
  13. Giới thiệu hệ thống Notification (updating)
  14. Thay đổi cấu trúc thư mục “app” (updating)
  15. Giới thiệu Mailables (updating)
  16. Auth scaffold sử dụng mã biên soạn sẵn –bao gồm Vuejs– (updating)
  17. Định nghĩa console commands qua closure (updating)
  18. Cập nhật queue workers (updating)

1. Giới thiệu Laravel Echo

Tháng 5-2016, Taylor Otwell đã giới thiệu về Laravel Echo trên Laracast, demo một ứng dụng thời gian thực sử dụng Vue.js, Laravel Spark và Laravel Echo.

Vậy Laravel Echo là gì? Về cơ bản nó là 1 công cụ hỗ trợ bạn tạo ra một ứng dụng thời gian thực với WebSockets.

Laravel Echo được chia làm hai phần: các cải tiến cho Laravel Event broadcasting và một package JavaScript:

  • Các thành phần backend của Laravel Echo sẽ được mặc định thêm vào Laravel core ở phiên bản 5.3. Có thể sử dụng phần backend này với bất kì JavaScript frontend nào, không bắt buộc là thư viện Echo JavaScript, nhưng với Echo JavaScript thì hỗ trợ tốt hơn.
  • Thư viện Echo JavaScript có thể import qua NPM. Hoạt động với Pusher JS hoặc Socket.io.

Laravel Echo vẫn đang được phát triển. Hiện tại chưa có tài liệu nào về Laravel Echo nên chúng ta sẽ tìm hiểu kĩ hơn về Laravel Echo khi có phiên bản chính thức. Trước đó, bạn có thể xem cách tạo ra một ứng dụng thời gian thực với Laravel Echo qua video của Taylor Otwell hoặc bài viết của Matt Stauffer.

2. Biến $loop mới

Laravel blade cung cấp các chỉ thị điều khiển các cấu trúc lặp, điều kiện được mở đầu bằng @. Các chỉ thị quen thuộc như @if, @for, @foeach.

@foreach($posts as $post)
    <li>{!! $post->name !!}<li>
@endforeach

Laravel 5.3 sẽ có một biến $loop có sãn trong mỗi vòng lặp, $loop là một object chưa thông tin về vòng lặp hiện tại:

  • index: chỉ mục của vòng lặp hiện tại. Trả về 1 ở vòng lặp đầu tiên.
  • remaining: số lần lặp còn lại. Nếu đang ở vòng lặp thứ i của n vòng lặp thì trả về n - i.
  • count: số lượng items trong vòng lặp.
  • first: giá trị boolean, kiểm tra vòng lặp hiện tại là vòng lặp đầu tiên.
  • last: giá trị boolean, kiểm tra vòng lặp hiện tại là vòng lặp cuối cùng.
  • depth: giá trị integer, trả về chiều sâu của vòng lặp. Ví dụ: trả ra 1 với một vòng lặp, trả ra 2 với một vòng lặp nằm trong một vòng lặp khác…
  • parent: nếu vòng lặp hiện tại ở trong một vòng lặp khác thì trả về một tham chiếu đến biến $loop ở vòng lặp cha, nếu không thì trả về null.

Biến $loop này sẽ hỗ trợ chúng ta làm một số việc như:

@foreach($pages as $page)
    // Kiểm tra trang hiện tại
    <li class="@if($loop->first) first-page @elseif($loop->last) last-page @endif">
        // Hiển thị trang hiện tại trên tổng số trang
        {{ $page->title }} ({{ $loop->index }} / {{ $loop->count }})
    </li>
@endforeach

// Trường hợp item có các item con
@foreach ($pages as $page)
    <li>{{ $loop->index }}: {{ $page->title }}
        @if ($page->hasChildren())
            <ul>
                @foreach ($page->children() as $child)
                    <li>
                        {{ $loop->parent->index }}.{{ $loop->index }}:
                        {{ $child->title }}
                    </li>
                @endforeach
            </ul>
        @endif
    </li>
@endforeach

3. Thêm tham số mới cho hàm FirstOrCreate

Trong phiên bản 5.3 chúng ta có thể truyền thêm 1 array giá trị cho function firstOrCreate. Array này mang những giá trị mà ta muốn gán cho đối tượng. Một ví dụ đơn giản về sự thay đổi này:

// Trước đây
$tag = Tag::firstOrCreate(['slug' => 'laravel-5.3']);
$tag->fill(['label' => 'Laravel 5.3'])->save();

// Bây giờ
$tag = Tag::firstOrCreate(
    ['slug' => 'laravel-5.3'],
    ['label' => 'Laravel 5.3']
);

// Code ít hơn một chút rồi

4.Global helper cache()

Phiên bản 5.3 thêm cache() vào global helper. Cũng giống như session() hay cookie(), cache() có 3 phương thức chính get set hoặc trả về thể hiện của backing service:

  • cache('abc', null) lấy ra giá trị đã được cache với tên abc hoặc trả về null nếu không tồn tại.
  • cache(['abc' => 'def'], 5) gán giá trị của abc cho def trong thời gian 5 phút
  • cache() trả về một thể hiện của CacheManager.

5. Thêm phương thức truy vấn với JSON-column cho where() và update()

Trước đây chúng ta vẫn có thể lưu dữ liệu kiểu JSON nhưng thực tế là lưu dưới dạng text. Trong phiên bản 5.7, MySQL đã giới thiệu về kiểu dữ liệu JSON. Laravel 5.3 cung cấp cho chung ta một cú pháp đơn giản để thao tác dựa trên keys trong một cột dữ liệu JSON. Cùng tìm hiểu về sự thay đổi này qua ví dụ sau:

Chúng ta có một table contacts

...
class CreateContactsTable extends Migration
{
    public function up()
    {
        Schema::create('contacts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->json('meta'); // Kiểu dữ liệu JSON
            $table->timestamps();
        });
    }
}

Giả sử trường dữ liệu meta có dạng:

{
    "id": 1,
    "name": "Akira",
    "meta": {
        "wants_newsletter": true,
        "favorite_color": "black"
    }
}

Để tham chiếu đến thuộc tính trong trường JSON, chúng ta bắt đầu bằng tên trường với mũi tên -> tới thuộc tính cần tham chiếu.

Tìm kiếm trong cột JSON với where()

$users = DB::table('users')
    ->where('meta->favorite_color', 'black')
    ->get();

Câu lệnh này sẽ tìm kiếm user có meta chứa favorite_colorblack.

Update dữ liệu cột JSON với update()

DB::table('users')
    ->where('id', 1)
    ->update(['meta->wants_newsletter' => false]);

Trường hợp meta chưa có thuộc tính wants_newsletter trước đó thì vẫn có thể update được.

Hiện tại MariaDB chưa có JSON columns, và PostgreSQL có JSON columns nhưng tính năng này dường như không hoạt động được. Nên hiện tại có thể coi đây là một tính năng cho MySQL 5.7+.

6. Những thực thi nâng cao với Collection::where

Trước đây để thực hiện việc tìm kiếm trong Collection chúng ta có thể sử dụng filter(), reject(), where()nhưng where() chỉ thực hiện phép so sánh nhất quán ===.

Ở phiên bản 5.3 chúng ta có thể sử dụng nhiều toán tử hơn với where() như = == === != !== <= >= < ><>.

7. Validation kích thước ảnh

Trong phiên bản 5.3 chúng ta có thể validation kích thước ảnh khi upload, được gọi qua từ khóa dimensions. Validation này nhận các tham số:

  • min_width: chiều rộng tối thiểu
  • max_width: chiều rộng tối đa
  • min_height: chiều cao tối thiểu
  • max_height: chiều cao tối đa
  • width: chiều rộng cố định
  • height: chiều cao cố định
  • ratio: tỉ lệ ảnh (width/height)

// ImageController
    public function postImage(Request $request)
    {
        $this->validate($request, [
             'avatar' => 'dimensions:max_width=600,max_height=400,ratio:3/2'
        ]);
    }

8. Tùy biến templates phân trang

Ở phiên bản 5.3 có 2 cách để tùy biến templates phân trang:

#Publish build-in

Là cách đơn giản nhất, chạy php artisan vendor:publish để pulish template vào thư mục vendor/pagination và chỉnh sửa nó ở đây. Nếu cần tùy biến ở một số trường hợp nhất định thì có thể sử dụng cách thứ 2.

#Chọn file template thủ công

Tạo một view ví dụ resources/views/partials/pagination.blade.php và đăng ký trong function boot() của service provider \Illuminate\Pagination\LengthAwarePaginator::defaultView('partials.paginator').

Trường hợp chỉ muốn tùy biến phân trang cho một trang nhất định nào đó có thể truyền trực tiếp view vào function link() như sau:

{{ $users->links('partials.paginator') }}

9. Thay đổi route

Ở phiên bản 5.2, ban đầu chúng ta thấy file route.php được chia làm 2 group webapi, nhưng sau đó đã được loại bỏ. Thay vào đó là multiple middleware groups, một cho web và một cho api.

Group web chứa mọi thứ mà user bình thường cần: sessions, cookies, CSRF protection, etc. Group api thì “nhẹ hơn” nó chỉ chứa middleware “throttle”, quản lý những trường hợp stateless REST API.

Ở phiên bản 5.3 app/Http/routes.php được chuyển về thư mục gốc routes/ và được chia làm 2 file web.phpapi.php. Và có thể đoán, web.php được bao bởi web middleware và api.php được bao bởi api middleware.

Có một số lợi ích trong việc này:

  • Đầu tiên, chúng ta có được sự gợi ý và dễ dàng thực hiện việc phân biệt giữa web route và api route.
  • Thứ hai, với việc có nhiều file route sẽ giúp cho các developers trong dự án tự do điều chỉnh file route của mình.
  • Thứ ba, việc dời routes ra khỏi thư mục app/ khiến người mới dễ dàng tiếp cận hơn, đồng thời khiến app/hoàn toàn trở thành thư mục chuẩn PSR-4-autoloaded.

Nếu muốn tùy biến file route hoặc thêm file route của riêng mình, bạn có thể kiểm tra tại App\Providers\RouteServiceProvider:

...
    public function map()
    {
        $this->mapWebRoutes();

        $this->mapApiRoutes();

        //
    }

    protected function mapWebRoutes()
    {
        Route::group([
            'namespace' => $this->namespace, 'middleware' => 'web',
        ], function ($router) {
            require base_path('routes/web.php');
        });
    }

    protected function mapApiRoutes()
    {
        Route::group([
            'middleware' => ['api', 'auth:api'],
            'namespace' => $this->namespace,
            'prefix' => 'api',
        ], function ($router) {
            require base_path('routes/api.php');
        });
    }

10. Giới thiệu Laravel Scout

Laravel Scout là full-text search dựa trên driver cho Eloquent. Scout hỗ trợ việc đánh index và tìm kiếm nội dung trong Eloquent models. Hiện tại Scout làm việc được với Algolia, nhưng Taylor Otwell đang tham khảo ý kiến cộng đồng về những dịch vụ full-text search khác như ElasticSearch.

Scout là một Laravel package riêng biệt, giống như Cashier, bạn cần phải cài đặt nó với Composer. Cần phải thêm trait s của Scoute vào model để báo cho nó biết cần phải lắng nghe những sự kiện khi một thể hiện của model được sửa đổi và cập nhật search index.

Sau khi cài đặt scout chúng ta có thể thực hiện những thao tác như:

Review::search('Llew')->get();
Review::search('Llew')->paginate(20);
Review::search('Llew')->where('account_id', 2)->get();

Chúng ta sẽ tìm hiểu kĩ hơn về Laravel Scout trong một bài viết khác. Các bạn cũng có thể tham khảo bài viết của Matt Stauffer.

(Updating…)