包开发

Introduction

包是为 Laravel 添加功能的主要方式。包可能是处理日期的好方法,例如Carbon 或允许您将文件与 Eloquent 模型(如 Spatie 的)相关联的包Laravel 媒体库.

有不同类型的包。有些包是独立的,这意味着它们可以与任何 PHP 框架一起使用。 Carbon 和 PHPUnit 是独立包的示例。这些包中的任何一个都可以通过在你的composer.json 文件。

另一方面,其他包专门用于 Laravel。这些包可能有专门用于增强 Laravel 应用程序的路由、控制器、视图和配置。本指南主要涵盖 Laravel 特定包的开发。

关于立面的注意事项

在编写 Laravel 应用程序时,使用契约或外观通常并不重要,因为两者提供的可测试性水平基本相同。但是,在编写包时,您的包通常不会访问 Laravel 的所有测试助手。如果你希望能够像将包安装在典型的 Laravel 应用程序中一样编写包测试,你可以使用管弦乐测试台 包裹。

包发现

在 Laravel 应用程序中config/app.php 配置文件,providers 选项定义了应该由 Laravel 加载的服务提供者列表。当有人安装您的软件包时,您通常希望您的服务提供商包含在此列表中。无需用户手动将您的服务提供商添加到列表中,您可以在extra 包裹的一部分composer.json 文件。除了服务提供商,您还可以列出任何facades 你想注册:

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

一旦你的包被配置为发现,Laravel 将在安装时自动注册它的服务提供者和门面,为你的包的用户创造一个方便的安装体验。

选择退出包发现

如果您是包的使用者并且想要禁用包的包发现,您可以在extra 您的应用程序的一部分composer.json 文件:

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

您可以使用禁用所有包的包发现* 应用程序中的字符dont-discover 指示:

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

服务供应商

服务供应商 是你的包和 Laravel 之间的连接点。服务提供者负责将事物绑定到 Laravel 的服务容器 并通知 Laravel 在哪里加载包资源,如视图、配置和语言文件。

服务提供商扩展了Illuminate\Support\ServiceProvider 类并包含两个方法:registerboot.基地ServiceProvider 类位于illuminate/support Composer 包,您应该将其添加到您自己的包的依赖项中。要了解有关服务提供商的结构和目的的更多信息,请查看他们的文档.

Resources

Configuration

通常,您需要将包的配置文件发布到应用程序的config 目录。这将允许您的包的用户轻松覆盖您的默认配置选项。要允许发布配置文件,请调用publishes 方法来自boot 您的服务提供商的方法:

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

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

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

Warning
你不应该在你的配置文件中定义闭包。当用户执行时,它们不能被正确序列化config:cache 工匠命令。

默认包配置

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

mergeConfigFrom 方法接受包配置文件的路径作为第一个参数,应用程序的配置文件副本的名称作为第二个参数:

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

Warning
此方法仅合并配置数组的第一级。如果您的用户部分定义了多维配置数组,则不会合并缺少的选项。

Routes

如果您的包裹包含路线,您可以使用loadRoutesFrom 方法。此方法将自动确定应用程序的路由是否已缓存,如果路由已被缓存,则不会加载您的路由文件:

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

Migrations

如果您的包裹包含数据库迁移, 你可以使用loadMigrationsFrom 方法来通知 Laravel 如何加载它们。这loadMigrationsFrom 方法接受包迁移的路径作为其唯一参数:

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

一旦你的包的迁移被注册,它们将在php artisan migrate 命令被执行。您不需要将它们导出到应用程序的database/migrations 目录。

语言文件

如果您的包裹包含语言文件, 你可以使用loadTranslationsFrom 方法来通知 Laravel 如何加载它们。例如,如果您的包名为courier,您应该将以下内容添加到您的服务提供商的boot 方法:

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

包翻译行使用package::file.line 语法约定。所以,你可以加载courier 包裹的welcome 线从messages 文件如下:

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

发布语言文件

如果您想将包的语言文件发布到应用程序的lang/vendor 目录,您可以使用服务提供商的publishes 方法。这publishes 方法接受一组包路径及其所需的发布位置。例如,发布语言文件courier 包,您可以执行以下操作:

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

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

现在,当你的包的用户执行 Laravel 的vendor:publish Artisan 命令,您的包的语言文件将被发布到指定的发布位置。

Views

注册您的包裹views 使用 Laravel,你需要告诉 Laravel 视图所在的位置。您可以使用服务提供商的loadViewsFrom 方法。这loadViewsFrom 方法接受两个参数:视图模板的路径和包的名称。例如,如果您的包裹名称是courier,您会将以下内容添加到您的服务提供商的boot 方法:

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

包视图使用package::view 语法约定。因此,一旦您的视图路径在服务提供商中注册,您就可以加载dashboardcourier 像这样包装:

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

覆盖包视图

当您使用loadViewsFrom 方法,Laravel 实际上为你的视图注册了两个位置:应用程序的resources/views/vendor 目录和您指定的目录。所以,使用courier 以 package 为例,Laravel 会先检查自定义版本的视图是否已经放置在resources/views/vendor/courier 开发者的目录。然后,如果视图还没有被自定义,Laravel 将搜索你在调用中指定的包视图目录loadViewsFrom.这使包用户可以轻松自定义/覆盖包的视图。

发布视图

如果您想让您的视图可用于发布到应用程序的resources/views/vendor 目录,您可以使用服务提供商的publishes 方法。这publishes 方法接受一组包视图路径及其所需的发布位置:

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

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

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

查看组件

如果您正在构建一个使用 Blade 组件的包或将组件放置在非常规目录中,您将需要手动注册您的组件类及其 HTML 标签别名,以便 Laravel 知道在哪里可以找到该组件。您通常应该在boot 您包裹的服务提供商的方法:

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);
}

一旦你的组件被注册,它就可以使用它的标签别名来呈现:

<x-package-alert/>

自动加载包组件

或者,您可以使用componentNamespace 按照惯例自动加载组件类的方法。例如,一个Nightshade 包裹可能有CalendarColorPicker 驻留在Nightshade\Views\Components 命名空间:

use Illuminate\Support\Facades\Blade;

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

这将允许使用它们的供应商名称空间使用包组件package-name:: 句法:

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

Blade 将通过组件名称的 pascal 大小写自动检测链接到该组件的类。使用“点”表示法也支持子目录。

匿名组件

如果你的包包含匿名组件,它们必须放在components 包的“views”目录的目录(由loadViewsFrom 方法).然后,您可以通过在组件名称前加上包的视图命名空间来渲染它们:

<x-courier::alert />

“关于”工匠命令

Laravel 的内置about Artisan 命令提供应用程序环境和配置的概要。软件包可以通过以下方式将附加信息推送到此命令的输出AboutCommand 班级。通常,此信息可能是从您的包裹服务提供商处添加的boot 方法:

use Illuminate\Foundation\Console\AboutCommand;

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

Commands

要使用 Laravel 注册你的包的 Artisan 命令,你可以使用commands 方法。此方法需要一组命令类名。注册命令后,您可以使用工匠 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,
        ]);
    }
}

公共资产

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

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

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

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

发布文件组

您可能希望单独发布包资产和资源组。例如,您可能希望允许您的用户发布您的包的配置文件,而不用被迫发布您的包的资产。您可以通过在调用publishes 来自包的服务提供商的方法。例如,让我们使用标签为courier 包裹 (courier-configcourier-migrations) 在里面boot 包裹服务提供商的方法:

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

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

现在您的用户可以通过在执行时引用他们的标签来单独发布这些组vendor:publish 命令:

php artisan vendor:publish --tag=courier-config
豫ICP备18041297号-2