Package Development

Giới thiệu

Packages là cách chính thức để thêm chức năng vào trong Laravel. Package có thể là bất cứ thứ gì từ việc xử lý ngày giờ như Carbon, hay nguyên bộ framework testing như Behat.

Tất nhiên là có nhiều loại package. Một số package thì stand-alone, nghĩa là chúng có thể hoạt động với bất kì framework nào, không chỉ là Laravel. Cả Carbon và Behat là ví dụ về stand-alone package.Bất cứ package nào có thể sử dụng với Laravel chỉ đơn giản là yêu cầu trong file composer.json file.

Mặt khác, một số package lại được tạo ra với mục đích sử dụng trong Laravel. Những package nào có route, controller, view và các cấu hình nhằm mục đích cải thiện ứng dụng Laravel. Hướng dẫn này phần lớn sẽ nói về việc phát triển các package dành cho Laravel.

A Note On Facades

Khi viết ứng dụng Laravel, nó thường không quan tâm nếu bạn sử dụng contracts hoặc facades vì cả hai cơ bản là giống nhau. Tuy nhiên, khi viết packages, tốt nhất là đung contracts thay vì facades. Vì package của bạn sẽ không thể truy cập đến tất cả các helpers testing của Laravel, nó sẽ dễ dàng để mock hoặc stub một contract hơn là mock một facade.

Service Providers

Service providers là điểm két nối giữa package của bạn và Laravel. Một service provider chịu trách nhiệm binding các thành phần vào trong service container của Laravel và thông báo cho Laravel vị trí để load các tài nguyên của package như views, cấu hình, và các file localization.

Một service provider kế thừa từ class Illuminate\Support\ServiceProvider class and contains two methods: registerboot. Class base ServiceProvider nằm trong Composer package là illuminate/support mà bạn cần phải thêm vào trong dependencies trong package của bạn.. Để tìm hiểu thêm về cấu trúc và mục đích của service providers, xem tại their documentation.

Routing

Để khai báo các routes cho package của bạn, đơn giản chỉ cần require các route file trong hàm boot của service provider nằm trong package của bạn. Từ trong route file, bạn có thể sử dụng Illuminate\Support\Facades\Route facade to register routes như là làm với một ứng dụng Laravel bình thường:

/**
 * Perform post-registration booting of services.
 *
 * @return  void
 */
public function boot()
{
    if (! $this->app->routesAreCached()) {
        require __DIR__.'/../../routes.php';
    }
}

Resources

Cấu hình

Thông thường, bạn cần phải publish file cấu hình package của bạn trong thư mục config. Nó cho phép người dùng dễ dàng chỉnh sửa file cấu hình mặc định. Để cho phép file cấu hình được publish, gọi làm publishes từ phương thức boot của service provider:

/**
 * Perform post-registration booting of services.
 *
 * @return  void
 */
public function boot()
{
    $this->publishes([
        __DIR__.'/path/to/config/courier.php' => config_path('courier.php'),
    ]);
}

Bây giờ, Khi người dùng thực thi lệnh vendor:publish, file của bạn sẽ được copy sang thư mục được chỉ định. Tất nhiên, khi file cấu hình đã được published, giá trị của nó có thể được tuy cập như những file cấu hình khác:

$value = config('courier.option');

Cấu hình Package mặc định

Bạn cũng có thể merge file cấu hình package của bạn với các bản copy của ứng dụng đã được published. Nó cho phép người dùng chỉ định nghĩa những thứ họ muốn ghi đè trong file copy cấu hình được published. Để merge file cấu hình, sử dụng hàm mergeConfigFrom bên trong hàm register của service provider:

/**
 * Register bindings in the container.
 *
 * @return  void
 */
public function register()
{
    $this->mergeConfigFrom(
        __DIR__.'/path/to/config/courier.php', 'courier'
    );
}

Migrations

Nếu package của bạn chưa database migrations, bạn có thể sử dụng hàm loadMigrationsFrom để thông báo cho Laravel load chúng. Hàm loadMigrationsFrom chấp nhận đường dẫn file migrations là đối số duy nhất:

/**
 * Perform post-registration booting of services.
 *
 * @return  void
 */
public function boot()
{
    $this->loadMigrationsFrom(__DIR__.'/path/to/migrations');
}

Khi migrations của package đã được đăng ký registered, nó sẽ tự động chạy khi lệnh php artisan migrate được thực thi. Bạn không cần export chúng vào thư mục chính database/migrations.

Translations

Nếu package của bạn chứa translation files, bạn có thể dùng hàm loadTranslationsFrom để thông báo cho Laravel load chúng. Ví dụ, nếu package có tên là courier, bạn nên thêm nó vào hàm boot của service provider như sau:

/**
 * Perform post-registration booting of services.
 *
 * @return  void
 */
public function boot()
{
    $this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier');
}

File dịch trong package được tham chiếu sử dụng hai dấu hai chấm package::file.line. Vì vậy, bạn có thể load courier package's welcome từ filw messages như sau:

echo trans('courier::messages.welcome');

Publishing Translations

Nếu bạn muốn publish các file dịch trong package tới thư mục resources/lang/vendor, publishes trong service provider. Hàm publishes nhận một mảng các đường dẫn của package và vị trí publish tương ứng. Ví dụ, để publish các file dịch cho package courier, thì làm như sau:

/**
 * Perform post-registration booting of services.
 *
 * @return  void
 */
public function boot()
{
    $this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier');

    $this->publishes([
        __DIR__.'/path/to/translations' => resource_path('lang/vendor/courier'),
    ]);
}

Now, when users of your package execute Laravel's vendor:publish Artisan command, your package's translations will be published to the specified publish location.

Views

Để đăng kí views trong package của bạn vào Laravel, bạn cần phải cho Laravel biết vị trí của các views ở đâu. Bạn có thể làm việc này thông qua hàm loadViewsFrom của service provider. Hàm loadViewsFrom nhận hai tham số: đương dẫn tới view template và tên package của bạn. Ví dụ, nếu tên package của bạn là courier, , thêm phần dưới đây vào trong hàm boot của serive provider:

/**
 * Perform post-registration booting of services.
 *
 * @return  void
 */
public function boot()
{
    $this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');
}

Thư viện views được tham chiếu sử dụng hai dấu hai chấm package::view. Vì thế, bạn có thể load admin từ package courier như sau:

Route::get('admin', function () {
    return view('courier::admin');
});

Overriding Package Views

Khi bạn sử dụng hàm loadViewsFrom , Laravel hay đăng kí tại resources/views/vendor của ứng dụng và một nằm trong thư mục mà bạn chỉ định. Vì thế, với ví dụ courier, hì: khi có yêu cầu một package view, Laravel sẽ đầu tiên thực hiện kiểm tra nếu một version riêng của view được cung cấp bởi lập trình viên trong resources/views/vendor/courier. Rồi sau đó, nếu view chưa được tuỳ chỉnh, Laravel sẽ tìm trong thư mục view của package mà bạn chỉ định trong hàm loadViewsFrom. Điều này làm cho người sử dụng dễ dàng có thể tuỳ chỉnh hay ghi đè lên thay thế views trong package của bạn.

Publishing Views

Nếu bạn muốn làm cho views có thể sẵn sàng cho việc publish tới thư mục resources/views/vendor của ứng dụng, bạn có thể sử dụng hàm publishes của service provider. Hàm publishes nhận một mảng bao gồm các đường dẫn tới view của package và đường đãn publish tương ứng:

/**
 * Perform post-registration booting of services.
 *
 * @return  void
 */
public function boot()
{
    $this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');

    $this->publishes([
        __DIR__.'/path/to/views' => resource_path('views/vendor/courier'),
    ]);
}

Bay giờ, khi người dùng thực hiện câu lệnh vendor:publish Artisan, với package của bạn, các view trong package sẽ được copy tới vị trí được thiết lập sẵn trong service provider.

Commands

Để đăng ký Artisan commands cho package với Laravel, bạn có thể dùng hàm commands. Hàm này sẽ chấp nhật một mảng tên command class. Khi commands được đăng ký, bạn có thể thực thi bằng Artisan CLI:

/**
 * Bootstrap the application services.
 *
 * @return  void
 */
public function boot()
{
    if ($this->app->runningInConsole()) {
        $this->commands([
            FooCommand::class,
            BarCommand::class,
        ]);
    }
}

Public Assets

Package có thể có assets như là JavaScript, CSS, và images. Để publish assets đó vào thư mụ public của ứng dụng, sử đụng hàm publishes của service provider. Trong ví dụ này, chúng ta thêm một public asset group tag, nó có thể được sử dụng để publish groups liên quan đến assets:

/**
 * Perform post-registration booting of services.
 *
 * @return  void
 */
public function boot()
{
    $this->publishes([
        __DIR__.'/path/to/assets' => public_path('vendor/courier'),
    ], 'public');
}

Bây giờ, Khi người dùng thực thi package của bạn bằng lệnh vendor:publish, nhưng assets sẽ được copied vào đường dẫn được chỉ định. Vì vậy, thông thường bạn có thể dùng để ghi đè assets mỗi khi package được cập nhật, bạn dùng cờ --force:

php artisan vendor:publish --tag=public --force

Publishing File Groups

Bạn có thể muốn publish groups của package và and resources riẻng. Ví dụ, bạn muốn cho phép người dùng publish file cấu hình mà không cần được forced vào publish your package's assets. Bạn có thể sử dụng nó bằng "tagging" khi gọi hàm publishes từ service provider của package. Ví dụ, chúng ta sử dụng tags để định nghĩa 2 publish groups trong hàm boot của một package service provider:

/**
 * Perform post-registration booting of services.
 *
 * @return  void
 */
public function boot()
{
    $this->publishes([
        __DIR__.'/../config/package.php' => config_path('package.php')
    ], 'config');

    $this->publishes([
        __DIR__.'/../database/migrations/' => database_path('migrations')
    ], 'migrations');
}

Bày giờ người dùng có thể publish groups đó riêng biệt bởi tag khi thực thi lệnh vendor:publish:

php artisan vendor:publish --tag=config
Nguồn: https://laravel.com/docs/5.3/packages