翻译进度
9
分块数量
1
参与人数

扩展包开发

这是一篇协同翻译的文章,你可以点击『我来翻译』按钮来参与翻译。


扩展包开发

简介

扩展包是为 Laravel 添加功能的主要方式。扩展包可以提供各种功能,例如用于处理日期的优秀工具 Carbon,或者像 Spatie 的 Laravel Media Library 这样允许你将文件与 Eloquent 模型关联的扩展包。

扩展包有不同的类型。有些扩展包是独立的,这意味着它们可以与任何 PHP 框架一起使用。Carbon 和 Pest 就是独立扩展包的例子。只需在 composer.json 文件中声明这些扩展包的依赖,就可以在 Laravel 中使用它们。

另一方面,还有一些扩展包是专门为 Laravel 设计的。这些扩展包可能包含专门用于增强 Laravel 应用程序的路由、控制器、视图和配置。本指南主要介绍如何开发这些专门针对 Laravel 的扩展包。

关于门面的说明

在编写 Laravel 应用程序时,使用契约还是门面通常并不重要,因为两者基本上具有相同的可测试性。但是,在开发扩展包时,你的扩展包通常无法使用 Laravel 的所有测试辅助工具。如果你希望能够像扩展包安装在普通 Laravel 应用程序中一样编写测试,可以使用 Orchestral Testbench 扩展包。

无与伦比 翻译于 3天前

扩展包自动发现

Laravel 应用程序的 bootstrap/providers.php 文件包含 Laravel 应加载的服务提供者列表。但是,你可以在扩展包的 composer.json 文件的 extra 部分中定义服务提供者,使 Laravel 自动加载它,而不需要用户手动将服务提供者添加到列表中。除了服务提供者之外,你还可以列出希望注册的任何门面:

"extra": {
    "laravel": {
        "providers": [
            "Barryvdh\\Debugbar\\ServiceProvider"
        ],
        "aliases": {
            "Debugbar": "Barryvdh\\Debugbar\\Facade"
        }
    }
},

一旦你的扩展包配置了自动发现功能,Laravel 就会在安装该扩展包时自动注册其服务提供者和门面,从而为扩展包的用户提供便捷的安装体验。

禁用扩展包自动发现

如果你是扩展包的使用者,并希望禁用某个扩展包的自动发现功能,可以在应用程序的 composer.json 文件的 extra 部分中列出该扩展包的名称:

"extra": {
    "laravel": {
        "dont-discover": [
            "barryvdh/laravel-debugbar"
        ]
    }
},

你可以在应用程序的 dont-discover 配置项中使用 * 字符,禁用所有扩展包的自动发现功能:

"extra": {
    "laravel": {
        "dont-discover": [
            "*"
        ]
    }
},

服务提供者

服务提供者是扩展包与 Laravel 之间的连接点。服务提供者负责将各种服务绑定到 Laravel 的服务容器中,并告知 Laravel 从何处加载扩展包的资源,例如视图、配置文件和语言文件。

服务提供者继承自 Illuminate\Support\ServiceProvider 类,并包含两个方法:register 和 boot。基础 ServiceProvider 类位于 illuminate/support Composer 扩展包中,你应该将其添加到自己扩展包的依赖项中。要了解有关服务提供者的结构和用途的更多信息,请查看服务提供者文档。

无与伦比 翻译于 3天前

Resources

Configuration

Typically, you will need to publish your package's configuration file to the application's config directory. This will allow users of your package to easily override your default configuration options. To allow your configuration files to be published, call the publishes method from the boot method of your service provider:

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->publishes([
        __DIR__.'/../config/courier.php' => config_path('courier.php'),
    ]);
}

Now, when users of your package execute Laravel's vendor:publish command, your file will be copied to the specified publish location. Once your configuration has been published, its values may be accessed like any other configuration file:

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

[!WARNING]
You should not define closures in your configuration files. They cannot be serialized correctly when users execute the config:cache Artisan command.

Default Package Configuration

You may also merge your own package configuration file with the application's published copy. This will allow your users to define only the options they actually want to override in the published copy of the configuration file. To merge the configuration file values, use the mergeConfigFrom method within your service provider's register method.

The mergeConfigFrom method accepts the path to your package's configuration file as its first argument and the name of the application's copy of the configuration file as its second argument:

/**
 * Register any package services.
 */
public function register(): void
{
    $this->mergeConfigFrom(
        __DIR__.'/../config/courier.php', 'courier'
    );
}

[!WARNING]
This method only merges the first level of the configuration array. If your users partially define a multi-dimensional configuration array, the missing options will not be merged.

Routes

If your package contains routes, you may load them using the loadRoutesFrom method. This method will automatically determine if the application's routes are cached and will not load your routes file if the routes have already been cached:

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->loadRoutesFrom(__DIR__.'/../routes/web.php');
}

Migrations

If your package contains database migrations, you may use the publishesMigrations method to inform Laravel that the given directory or file contains migrations. When Laravel publishes the migrations, it will automatically update the timestamp within their filename to reflect the current date and time:

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->publishesMigrations([
        __DIR__.'/../database/migrations' => database_path('migrations'),
    ]);
}

Language Files

If your package contains language files, you may use the loadTranslationsFrom method to inform Laravel how to load them. For example, if your package is named courier, you should add the following to your service provider's boot method:

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->loadTranslationsFrom(__DIR__.'/../lang', 'courier');
}

Package translation lines are referenced using the package::file.line syntax convention. So, you may load the courier package's welcome line from the messages file like so:

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

You can register JSON translation files for your package using the loadJsonTranslationsFrom method. This method accepts the path to the directory that contains your package's JSON translation files:

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->loadJsonTranslationsFrom(__DIR__.'/../lang');
}

Publishing Language Files

If you would like to publish your package's language files to the application's lang/vendor directory, you may use the service provider's publishes method. The publishes method accepts an array of package paths and their desired publish locations. For example, to publish the language files for the courier package, you may do the following:

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->loadTranslationsFrom(__DIR__.'/../lang', 'courier');

    $this->publishes([
        __DIR__.'/../lang' => $this->app->langPath('vendor/courier'),
    ]);
}

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

Views

To register your package's views with Laravel, you need to tell Laravel where the views are located. You may do this using the service provider's loadViewsFrom method. The loadViewsFrom method accepts two arguments: the path to your view templates and your package's name. For example, if your package's name is courier, you would add the following to your service provider's boot method:

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->loadViewsFrom(__DIR__.'/../resources/views', 'courier');
}

Package views are referenced using the package::view syntax convention. So, once your view path is registered in a service provider, you may load the dashboard view from the courier package like so:

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

Overriding Package Views

When you use the loadViewsFrom method, Laravel actually registers two locations for your views: the application's resources/views/vendor directory and the directory you specify. So, using the courier package as an example, Laravel will first check if a custom version of the view has been placed in the resources/views/vendor/courier directory by the developer. Then, if the view has not been customized, Laravel will search the package view directory you specified in your call to loadViewsFrom. This makes it easy for package users to customize / override your package's views.

Publishing Views

If you would like to make your views available for publishing to the application's resources/views/vendor directory, you may use the service provider's publishes method. The publishes method accepts an array of package view paths and their desired publish locations:

/**
 * Bootstrap the package services.
 */
public function boot(): void
{
    $this->loadViewsFrom(__DIR__.'/../resources/views', 'courier');

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

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

View Components

If you are building a package that utilizes Blade components or placing components in non-conventional directories, you will need to manually register your component class and its HTML tag alias so that Laravel knows where to find the component. You should typically register your components in the boot method of your package's service provider:

use Illuminate\Support\Facades\Blade;
use VendorPackage\View\Components\AlertComponent;

/**
 * Bootstrap your package's services.
 */
public function boot(): void
{
    Blade::component('package-alert', AlertComponent::class);
}

Once your component has been registered, it may be rendered using its tag alias:

<x-package-alert/>

Autoloading Package Components

Alternatively, you may use the componentNamespace method to autoload component classes by convention. For example, a Nightshade package might have Calendar and ColorPicker components that reside within the Nightshade\Views\Components namespace:

use Illuminate\Support\Facades\Blade;

/**
 * Bootstrap your package's services.
 */
public function boot(): void
{
    Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');
}

This will allow the usage of package components by their vendor namespace using the package-name:: syntax:

<x-nightshade::calendar />
<x-nightshade::color-picker />

Blade will automatically detect the class that's linked to this component by pascal-casing the component name. Subdirectories are also supported using "dot" notation.

Anonymous Components

If your package contains anonymous components, they must be placed within a components directory of your package's "views" directory (as specified by the loadViewsFrom method). Then, you may render them by prefixing the component name with the package's view namespace:

<x-courier::alert />

"About" Artisan Command

Laravel's built-in about Artisan command provides a synopsis of the application's environment and configuration. Packages may push additional information to this command's output via the AboutCommand class. Typically, this information may be added from your package service provider's boot method:

use Illuminate\Foundation\Console\AboutCommand;

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    AboutCommand::add('My Package', fn () => ['Version' => '1.0.0']);
}

Commands

To register your package's Artisan commands with Laravel, you may use the commands method. This method expects an array of command class names. Once the commands have been registered, you may execute them using the Artisan CLI:

use Courier\Console\Commands\InstallCommand;
use Courier\Console\Commands\NetworkCommand;

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    if ($this->app->runningInConsole()) {
        $this->commands([
            InstallCommand::class,
            NetworkCommand::class,
        ]);
    }
}

Optimize Commands

Laravel's optimize command caches the application's configuration, events, routes, and views. Using the optimizes method, you may register your package's own Artisan commands that should be invoked when the optimize and optimize:clear commands are executed:

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    if ($this->app->runningInConsole()) {
        $this->optimizes(
            optimize: 'package:optimize',
            clear: 'package:clear-optimizations',
        );
    }
}

Reload Commands

Laravel's reload command terminates any running services so they can be automatically restarted by a system process monitor. Using the reloads method, you may register your package's own Artisan commands that should be invoked when the reload command is executed:

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    if ($this->app->runningInConsole()) {
        $this->reloads('package:reload');
    }
}

Public Assets

Your package may have assets such as JavaScript, CSS, and images. To publish these assets to the application's public directory, use the service provider's publishes method. In this example, we will also add a public asset group tag, which may be used to easily publish groups of related assets:

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->publishes([
        __DIR__.'/../public' => public_path('vendor/courier'),
    ], 'public');
}

Now, when your package's users execute the vendor:publish command, your assets will be copied to the specified publish location. Since users will typically need to overwrite the assets every time the package is updated, they may use the --force flag:

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

Publishing File Groups

You may want to publish groups of package assets and resources separately. For instance, you might want to allow your users to publish your package's configuration files without being forced to publish your package's assets. You may do this by "tagging" them when calling the publishes method from a package's service provider. For example, let's use tags to define two publish groups for the courier package (courier-config and courier-migrations) in the boot method of the package's service provider:

/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->publishes([
        __DIR__.'/../config/package.php' => config_path('package.php')
    ], 'courier-config');

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

Now your users may publish these groups separately by referencing their tag when executing the vendor:publish command:

php artisan vendor:publish --tag=courier-config

Your users can also publish all publishable files defined by your package's service provider using the --provider flag:

php artisan vendor:publish --provider="Your\Package\ServiceProvider"

本文章首发在 LearnKu.com 网站上。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
贡献者:1
讨论数量: 0
发起讨论 只看当前版本


暂无话题~