Package Development
Table of Contents
Introduction
パッケージは、 Laravel に機能を追加する primary な方法です。パッケージは、Carbon のように日付を扱う素晴らしい方法や、Spatie のLaravel Media Library のように、ファイルを Eloquent models に関連付けることを可能にするパッケージなど、さまざまなものがあり得ます。
さまざまな種類のパッケージがあります。一部のパッケージはスタンドアロン型で、任意の PHP フレームワークで動作します。 Carbon と Pest はスタンドアロンパッケージの例です。これらのパッケージは、あなたのcomposer.jsonファイルで必要とされていれば Laravel と共に使用することができます。
一方、他のパッケージは特に Laravel と一緒に使用することを目的としています。これらのパッケージには、特に Laravel application を強化するために意図された routes 、コントローラー、 views 、そして設定があるかもしれません。このガイドは主に、 Laravel 特有のそれらのパッケージの開発をカバーします。
Facades についての注意
Laravel application を書く際は、 contracts を使用するか facades を使用するかは、基本的にはテスト可能性のレベルが同等であるため、特に問題はありません。しかし、パッケージを作成する場合、パッケージは通常、Laravel の testing helpers 全体にアクセスできません。パッケージのテストをまるで通常の Laravel application 内にインストールされたかのように書きたい場合、Orchestral Testbench パッケージを使用することができます。
Package Discovery
Laravel application のbootstrap/providers.phpファイルには、 Laravel によって読み込まれるべき service provider のリストが含まれています。しかし、 users が手動であなたの service providers をリストに追加する代わりに、パッケージのcomposer.jsonファイルのextraセクションで provider を定義することで、それが自動的に Laravel によって読み込まれるようにできます。 service providers に加えて、登録したいfacadesもリストに追加できます。
"extra": {
    "laravel": {
        "providers": [
            "Barryvdh\\Debugbar\\ServiceProvider"
        ],
        "aliases": {
            "Debugbar": "Barryvdh\\Debugbar\\Facade"
        }
    }
},
あなたのパッケージが検出用に設定されると、 Laravel は自動的にその register 、 service providers 、および facades をインストール時に登録し、パッケージの users にとって便利なインストール体験を作り出します。
パッケージディスカバリーのオプトアウト
パッケージの消費者であり、パッケージ検出を無効にしたい場合は、アプリケーションの composer.json ファイルの extra セクションにパッケージ名をリストすることができます:
"extra": {
    "laravel": {
        "dont-discover": [
            "barryvdh/laravel-debugbar"
        ]
    }
},
アプリケーションの dont-discover ディレクティブの中で * 文字を使用して、すべてのパッケージのパッケージディスカバリを無効にすることができます:
"extra": {
    "laravel": {
        "dont-discover": [
            "*"
        ]
    }
},
Service Providers
Service providersはあなたのパッケージと Laravel との間の接続ポイントです。Service providers は、Laravel のservice container ーにものをバインドする責任を持ち、Laravel にパッケージの resources(views、設定、言語ファイルなど)をどこからロードするかを告げます。
service provider は、Illuminate\Support\ServiceProvider class を拡張し、二つの method:registerとboot、を含んでいます。基本のServiceProvider class は、illuminate/support Composer パッケージ内に位置しており、 それを自身のパッケージの依存性に追加するべきです。 service providers の構造と目的について詳しく知るには、そのドキュメンテーションを確認してください。
Resources
Configuration
通常、パッケージの設定ファイルをアプリケーションの config ディレクトリに publish する必要があります。これにより、パッケージの users は default の設定 options を簡単に上書きすることができます。設定ファイルを公開するためには、 service provider の boot method から publishes method を呼び出します。
/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->publishes([
        __DIR__.'/../config/courier.php' => config_path('courier.php'),
    ]);
}
さて、パッケージの users が Laravel の vendor:publish command を実行すると、ファイルが指定されたパブリッシュ場所にコピーされます。設定が公開されると、その values は他の設定ファイルと同様にアクセスできます。
$value = config('courier.option');
WARNING
設定ファイルでクロージャを定義するべきではありません。 users が
config:cacheの Artisan command を実行するとき、正しくシリアライズできません。
Default パッケージ設定
あなたはまた、アプリケーションが公開しているコピーと自分のパッケージ設定ファイルを merge することができます。これにより、あなたの users が実際に上書きしたい options だけを公開コピーの設定ファイルで定義することができます。設定ファイルの values を merge するためには、あなたの service プロバイダの register method で mergeConfigFrom method を使用します。
mergeConfigFrom method は、第一引数としてパッケージの設定ファイルへの path を、第二引数として application の設定ファイルの名前を受け付けます:
/**
 * Register any application services.
 */
public function register(): void
{
    $this->mergeConfigFrom(
        __DIR__.'/../config/courier.php', 'courier'
    );
}
WARNING
この method は、設定の array の最初のレベルのみをマージします。あなたの users が多次元の設定 array を部分的に定義すると、欠けている options はマージされません。
Routes
あなたのパッケージが routes を含んでいる場合、 loadRoutesFrom method を使用してそれらをロードすることができます。この method は自動的にアプリケーションの routes がキャッシュされているかどうかを判断し、 routes がすでにキャッシュされていればあなたの routes ファイルはロードされません:
/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->loadRoutesFrom(__DIR__.'/../routes/web.php');
}
Migrations
あなたのパッケージがdatabasemigrationsを含んでいる場合、指定したディレクトリやファイルが migrations を含んでいることを Laravel に通知するために、publishesMigrations method を使用することができます。Laravel が migrations を公開すると、それらのファイル名内の timestamp が自動的に現在の日付と時間を反映するように更新されます:
/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->publishesMigrations([
        __DIR__.'/../database/migrations' => database_path('migrations'),
    ]);
}
言語ファイル
あなたのパッケージがlanguage filesを含んでいる場合、それらをロードする方法を Laravel に知らせるためにloadTranslationsFrom method を使用することができます。例えば、あなたのパッケージがcourierという名前である場合、以下をあなたの service プロバイダーのboot method に追加すべきです:
/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->loadTranslationsFrom(__DIR__.'/../lang', 'courier');
}
パッケージ翻訳ラインは、package::file.line syntax 規約を使用して参照されます。したがって、次のようにmessagesファイルからcourierパッケージのwelcomeラインをロードすることができます:
echo trans('courier::messages.welcome');
あなたは loadJsonTranslationsFrom method を使用してパッケージのための register JSON 翻訳ファイルを登録することができます。この method は、パッケージの JSON 翻訳ファイルが含まれているディレクトリへの path を受け入れます:
/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->loadJsonTranslationsFrom(__DIR__.'/../lang');
}
言語ファイルの公開
パッケージの言語ファイルを application のlang/vendorディレクトリに publish したい場合は、publishes method を使用することができます。このpublishes method は、パッケージの paths とその望ましい publish の場所を array として受け付けます。例えば、courierパッケージの言語ファイルを publish するには、次のようにします:
/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->loadTranslationsFrom(__DIR__.'/../lang', 'courier');
    $this->publishes([
        __DIR__.'/../lang' => $this->app->langPath('vendor/courier'),
    ]);
}
さて、あなたのパッケージの users が Laravel のvendor:publish Artisan command を実行すると、パッケージの言語ファイルが指定された publish 場所に公開されます。
Views
register するために、パッケージのviewsを Laravel に登録する必要があります。そのためには、 views が置かれている場所を Laravel に伝える必要があります。これは、loadViewsFromという service プロバイダの method を使用して行うことができます。 loadViewsFrom method は二つの引数を受け取ります:テンプレートの view の path とあなたのパッケージの名前です。例えば、パッケージの名前が courier の場合、以下のように service プロバイダの boot method に追加します:
/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->loadViewsFrom(__DIR__.'/../resources/views', 'courier');
}
Package views はpackage::view syntax 規約を用いて参照されます。ですので、一旦あなたの view path が service provider に登録されたら、courierパッケージからdashboard view をこのように読み込むことができます:
Route::get('/dashboard', function () {
    return view('courier::dashboard');
});
パッケージ Views のオーバーライド
あなたがloadViewsFromの method を使用すると、 Laravel は実際にあなたの views のために 2 つの場所を登録します:アプリケーションのresources/views/vendorディレクトリとあなたが指定したディレクトリです。したがって、courierパッケージを例にすると、 Laravel はまず、開発者がresources/views/vendor/courierディレクトリに配置した custom の view がないか確認します。次に、その view がカスタマイズされていない場合、 Laravel はあなたがloadViewsFromを呼び出すときに指定したパッケージの view ディレクトリを search します。これにより、パッケージの users はあなたのパッケージの views を簡単にカスタマイズ/上書きすることができます。
Views の公開
あなたが views をアプリケーションのresources/views/vendorディレクトリへ公開したいと考えているなら、 service プロバイダのpublishes method を使用することができます。publishes method は、パッケージの view パスとそれらが希望する publish 場所の array を受け入れます:
/**
 * Bootstrap the package services.
 */
public function boot(): void
{
    $this->loadViewsFrom(__DIR__.'/../resources/views', 'courier');
    $this->publishes([
        __DIR__.'/../resources/views' => resource_path('views/vendor/courier'),
    ]);
}
さて、あなたのパッケージの users が Laravel の vendor:publish Artisan command を実行すると、あなたのパッケージの views が指定された公開場所にコピーされます。
View コンポーネント
Blade コンポーネントを利用するパッケージを作成していたり、コンポーネントを非標準的な directory に配置している場合は、 Laravel が component をどこで見つけるかを知るために、 component class とその HTML タグエイリアスを手動で register しなければなりません。通常、パッケージの service provider のboot method でコンポーネントを register `すべきです:
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);
}
あなたの component が登録されたら、そのタグエイリアスを使用してレンダリングすることができます:
<x-package-alert/>
Autoloading Package Components
あるいは、componentNamespace method を使って、 component classes を規則に従って自動的に読み込むこともできます。例えば、Nightshadeパッケージには、Nightshade\Views\Components名前空間内に存在するCalendarとColorPickerコンポーネントがあるかもしれません:
use Illuminate\Support\Facades\Blade;
/**
 * Bootstrap your package's services.
 */
public function boot(): void
{
    Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');
}
これにより、package-name::の syntax を使用して、パッケージのコンポーネントをその vendor 名前空間で使用することができます。
<x-nightshade::calendar />
<x-nightshade::color-picker />
Blade は、 component の名前をパスカルケースにすることで、この component にリンクされた class を自動的に検出します。また、"dot" 表記を使用してサブディレクトリもサポートしています
匿名コンポーネント
もしパッケージに無名 component が含まれている場合、それらはパッケージの"views"ディレクトリー(loadViewsFrom methodにて指定されているように)のcomponentsディレクトリー内に配置しなければなりません。その後、パッケージの view ネームスペースで component の名前をプレフィックスとして、それらを render することができます:
<x-courier::alert />
"About" Artisan Command について
Laravel の組み込みaboutの Artisan command は、application の環境と設定の概要を提供します。パッケージは、AboutCommandの class を介して、この command の出力に追加情報をプッシュすることができます。通常、この情報はパッケージの serviceprovider のbootの method から追加することができます:
use Illuminate\Foundation\Console\AboutCommand;
/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    AboutCommand::add('My Package', fn () => ['Version' => '1.0.0']);
}
Commands
あなたのパッケージの Artisan commands を Laravel に登録するために、commands method を使用することができます。この method は、command class の名前の array を期待します。commands が登録されたら、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,
        ]);
    }
}
Public Assets
あなたのパッケージには、 JavaScript 、 CSS 、画像などのアセットが含まれている場合があります。これらのアセットをアプリケーションの public ディレクトリに publish するには、 service プロバイダの publishes method を使用します。この例では、関連するアセットのグループを簡単に publish するために使用できる public アセットグループタグを追加します:
/**
 * Bootstrap any package services.
 */
public function boot(): void
{
    $this->publishes([
        __DIR__.'/../public' => public_path('vendor/courier'),
    ], 'public');
}
さて、あなたのパッケージの users がvendor:publish command を実行すると、あなたのアセットは指定された publish の場所にコピーされます。 users は通常、パッケージが更新されるたびにアセットを上書きする必要がありますので、--forceフラグを使用することができます。
php artisan vendor:publish --tag=public --force
Publishing File Groups
あなたは、パッケージの資産や resources を別々に「 publish 」したいかもしれません。例えば、あなたのパッケージの設定ファイルを強制的にパッケージの資産を「 publish 」せずに、 users に「 publish 」を許可したくなるかもしれません。これはpublishes method をパッケージの「 service provider 」から呼び出す際に、それらに「tagging」することで実現できます。例えば、パッケージの「 service provider 」の boot method で、courier パッケージの「 publish 」の2つのグループ(courier-config と courier-migrations)を定義するために、「 tags 」を使用しましょう:
/**
 * 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');
}
現在、あなたの users は、vendor:publish command を実行する際に、そのタグを参照してこれらのグループを別々に publish することができます。
php artisan vendor:publish --tag=courier-config