Skip to content

包开发

介绍

包是向 Laravel 添加功能的主要方式。包可以是任何东西,从像 Carbon 这样处理日期的好方法,到像 Behat 这样完整的 BDD 测试框架。

当然,包有不同的类型。有些包是独立的,意味着它们可以与任何框架一起工作,而不仅仅是 Laravel。Carbon 和 Behat 都是独立包的例子。任何这些包都可以通过在 composer.json 文件中请求它们来与 Laravel 一起使用。

另一方面,其他包是专门为 Laravel 使用而设计的。这些包可能有路由、控制器、视图和配置,专门用于增强 Laravel 应用程序。本指南主要介绍那些专门为 Laravel 开发的包。

服务提供者

服务提供者 是您的包与 Laravel 之间的连接点。服务提供者负责将内容绑定到 Laravel 的 服务容器 中,并告知 Laravel 在哪里加载包资源,如视图、配置和本地化文件。

服务提供者扩展了 Illuminate\Support\ServiceProvider 类,并包含两个方法:registerboot。基础 ServiceProvider 类位于 illuminate/support Composer 包中,您应该将其添加到您自己的包的依赖项中。

要了解有关服务提供者的结构和目的的更多信息,请查看他们的文档

路由

要为您的包定义路由,只需在包服务提供者的 boot 方法中 require 路由文件。在路由文件中,您可以使用 Route facade 来注册路由,就像在典型的 Laravel 应用程序中一样:

php
/**
 * 执行服务的注册后引导。
 *
 * @return void
 */
public function boot()
{
    if (! $this->app->routesAreCached()) {
        require __DIR__.'/../../routes.php';
    }
}

资源

视图

要将包的视图注册到 Laravel,您需要告诉 Laravel 视图的位置。您可以使用服务提供者的 loadViewsFrom 方法来实现。loadViewsFrom 方法接受两个参数:视图模板的路径和包的名称。例如,如果您的包名为 "courier",请在服务提供者的 boot 方法中添加以下内容:

php
/**
 * 执行服务的注册后引导。
 *
 * @return void
 */
public function boot()
{
    $this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');
}

包视图使用双冒号 package::view 语法引用。因此,您可以像这样加载 courier 包的 admin 视图:

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

覆盖包视图

当您使用 loadViewsFrom 方法时,Laravel 实际上为您的视图注册了两个位置:一个在应用程序的 resources/views/vendor 目录中,另一个在您指定的目录中。因此,使用我们的 courier 示例:当请求包视图时,Laravel 将首先检查开发人员是否在 resources/views/vendor/courier 中提供了自定义版本的视图。然后,如果视图没有被自定义,Laravel 将搜索您在调用 loadViewsFrom 时指定的包视图目录。这使得最终用户可以轻松地自定义/覆盖您的包视图。

发布视图

如果您希望将视图发布到应用程序的 resources/views/vendor 目录中,可以使用服务提供者的 publishes 方法。publishes 方法接受一个包视图路径数组及其对应的发布位置。

php
/**
 * 执行服务的注册后引导。
 *
 * @return void
 */
public function boot()
{
    $this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');

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

现在,当您的包用户执行 Laravel 的 vendor:publish Artisan 命令时,您的包视图将被复制到指定位置。

翻译

如果您的包包含翻译文件,您可以使用 loadTranslationsFrom 方法来告知 Laravel 如何加载它们。例如,如果您的包名为 "courier",您应该在服务提供者的 boot 方法中添加以下内容:

php
/**
 * 执行服务的注册后引导。
 *
 * @return void
 */
public function boot()
{
    $this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier');
}

包翻译使用双冒号 package::file.line 语法引用。因此,您可以像这样加载 courier 包的 messages 文件中的 welcome 行:

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

发布翻译

如果您希望将包的翻译发布到应用程序的 resources/lang/vendor 目录中,可以使用服务提供者的 publishes 方法。publishes 方法接受一个包路径数组及其对应的发布位置。例如,要发布我们示例 courier 包的翻译文件:

php
/**
 * 执行服务的注册后引导。
 *
 * @return void
 */
public function boot()
{
    $this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier');

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

现在,当您的包用户执行 Laravel 的 vendor:publish Artisan 命令时,您的包翻译将被发布到指定位置。

配置

通常,您会希望将包的配置文件发布到应用程序自己的 config 目录中。这将允许您的包用户轻松覆盖您的默认配置选项。要发布配置文件,只需在服务提供者的 boot 方法中使用 publishes 方法:

php
/**
 * 执行服务的注册后引导。
 *
 * @return void
 */
public function boot()
{
    $this->publishes([
        __DIR__.'/path/to/config/courier.php' => config_path('courier.php'),
    ]);
}

现在,当您的包用户执行 Laravel 的 vendor:publish 命令时,您的文件将被复制到指定位置。当然,一旦您的配置被发布,它可以像任何其他配置文件一样访问:

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

默认包配置

您还可以选择将自己的包配置文件与应用程序的副本合并。这允许您的用户在发布的配置副本中仅包含他们实际想要覆盖的选项。要合并配置,请在服务提供者的 register 方法中使用 mergeConfigFrom 方法:

php
/**
 * 在容器中注册绑定。
 *
 * @return void
 */
public function register()
{
    $this->mergeConfigFrom(
        __DIR__.'/path/to/config/courier.php', 'courier'
    );
}

公共资源

您的包可能有 JavaScript、CSS 和图像等资源。要将这些资源发布到应用程序的 public 目录中,请使用服务提供者的 publishes 方法。在此示例中,我们还将添加一个 public 资源组标签,可用于发布相关资源组:

php
/**
 * 执行服务的注册后引导。
 *
 * @return void
 */
public function boot()
{
    $this->publishes([
        __DIR__.'/path/to/assets' => public_path('vendor/courier'),
    ], 'public');
}

现在,当您的包用户执行 vendor:publish 命令时,您的资源将被复制到指定位置。由于您通常需要在每次更新包时覆盖资源,您可以使用 --force 标志:

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

如果您希望确保您的公共资源始终是最新的,可以将此命令添加到 composer.json 文件的 post-update-cmd 列表中。

发布文件组

您可能希望单独发布包资源和资源组。例如,您可能希望您的用户能够发布包的配置文件,而不必同时发布包的资源。您可以通过在调用 publishes 方法时“标记”它们来实现。例如,让我们在包服务提供者的 boot 方法中定义两个发布组:

php
/**
 * 执行服务的注册后引导。
 *
 * @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');
}

现在,您的用户可以通过在使用 vendor:publish Artisan 命令时引用其标签名称来单独发布这些组:

php
php artisan vendor:publish --provider="Vendor\Providers\PackageServiceProvider" --tag="config"