メインコンテンツまでスキップ

パッケージ開発

はじめに

パッケージは Laravel に機能を追加する主要な方法です。パッケージには、Carbon のように日付を扱う素晴らしい方法や、Spatie の Laravel Media Library のように Eloquent モデルにファイルを関連付けることができるパッケージなど、さまざまなものがあります。

パッケージには異なる種類があります。一部のパッケージはスタンドアロンであり、任意の PHP フレームワークと連携します。Carbon や Pest はスタンドアロンパッケージの例です。これらのパッケージは、composer.json ファイルで要件として指定することで Laravel と一緒に使用できます。

一方、他のパッケージは Laravel との使用を前提としています。これらのパッケージには、Laravel アプリケーションを強化するために特に用意されたルート、コントローラ、ビュー、および設定が含まれる場合があります。このガイドは主に、Laravel 固有のパッケージの開発に焦点を当てています。

ファサードに関する注意

Laravel アプリケーションを作成する際、コントラクトを使用するかファサードを使用するかは一般的に問題になりません。なぜなら、どちらも基本的に同じレベルのテスト可能性を提供するからです。ただし、パッケージを作成する場合、パッケージは通常、すべての Laravel のテストヘルパーにアクセスできません。パッケージを通常の Laravel アプリケーション内にインストールされているかのようにパッケージのテストを記述したい場合は、Orchestral Testbench パッケージを使用できます。

パッケージの検出

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 クラスを拡張し、registerboot の 2 つのメソッドを含んでいます。ベースとなる ServiceProvider クラスは illuminate/support Composer パッケージにあり、自分のパッケージの依存関係に追加する必要があります。サービスプロバイダの構造と目的について詳しく知りたい場合は、そのドキュメント を参照してください。

リソース

設定

通常、パッケージの設定ファイルをアプリケーションの config ディレクトリに公開する必要があります。これにより、パッケージのユーザーが簡単にデフォルトの設定オプションを上書きできるようになります。設定ファイルを公開するためには、サービスプロバイダの boot メソッドから publishes メソッドを呼び出します:

    /**
* 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');

警告

設定ファイルでクロージャを定義しないでください。ユーザーが config:cache Artisan コマンドを実行すると、正しくシリアル化されません。

デフォルトパッケージ設定

独自のパッケージ設定ファイルをアプリケーションの公開されたコピーとマージすることもできます。これにより、ユーザーは公開された設定ファイルの中で実際に上書きしたいオプションのみを定義できます。設定ファイルの値をマージするには、サービスプロバイダの register メソッド内で mergeConfigFrom メソッドを使用します。

mergeConfigFrom メソッドは、最初の引数としてパッケージの設定ファイルへのパス、2 番目の引数としてアプリケーションの設定ファイルの名前を受け取ります:

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

警告

このメソッドは設定配列の最初のレベルのみをマージします。ユーザーが多次元の設定配列を部分的に定義した場合、欠落しているオプションはマージされません。

ルート

パッケージにルートが含まれている場合、loadRoutesFrom メソッドを使用してそれらをロードできます。このメソッドは、アプリケーションのルートがキャッシュされているかどうかを自動的に判断し、既にキャッシュされている場合はルートファイルをロードしません:

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

マイグレーション

パッケージにデータベースのマイグレーションが含まれている場合、publishesMigrationsメソッドを使用して、指定されたディレクトリやファイルがマイグレーションを含んでいることをLaravelに通知できます。 Laravelがマイグレーションを公開すると、そのマイグレーションのファイル名内のタイムスタンプが自動的に現在の日付と時刻に更新されます:

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

言語ファイル

パッケージに言語ファイルが含まれている場合、loadTranslationsFromメソッドを使用して、Laravelにそれらの読み込み方法を通知できます。 たとえば、パッケージの名前がcourierである場合、次のようにサービスプロバイダのbootメソッドに以下を追加する必要があります:

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

パッケージの翻訳行は、package::file.line構文規則を使用して参照されます。 したがって、courierパッケージのmessagesファイルからwelcome行を次のように読み込むことができます:

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

loadJsonTranslationsFromメソッドを使用して、パッケージのJSON翻訳ファイルを登録できます。 このメソッドは、パッケージのJSON翻訳ファイルを含むディレクトリへのパスを受け入れます:

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

言語ファイルの公開

パッケージの言語ファイルをアプリケーションの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コマンドを実行すると、パッケージの言語ファイルが指定された公開場所に公開されます。

ビュー

パッケージのビューをLaravelに登録するには、Laravelにビューがどこにあるかを伝える必要があります。 これは、サービスプロバイダのloadViewsFromメソッドを使用して行います。 loadViewsFromメソッドは、ビューテンプレートへのパスとパッケージの名前の2つの引数を受け入れます。 たとえば、パッケージの名前がcourierである場合、サービスプロバイダのbootメソッドに以下を追加します:

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

パッケージのビューは、package::view 構文規則を使用して参照されます。したがって、ビューパスがサービスプロバイダーに登録されると、courier パッケージから dashboard ビューを次のようにロードできます:

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

パッケージのビューのオーバーライド

loadViewsFrom メソッドを使用すると、実際には Laravel がビューのために 2 つの場所を登録します:アプリケーションの resources/views/vendor ディレクトリと指定したディレクトリ。 したがって、courier パッケージを例にすると、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 パッケージには、Nightshade\Views\Components ネームスペース内に存在する CalendarColorPicker コンポーネントが含まれているかもしれません:

    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 は、コンポーネント名をパスカルケースに変換してこのコンポーネントにリンクされたクラスを自動的に検出します。サブディレクトリも「ドット」表記を使用してサポートされています。

匿名コンポーネント

パッケージに匿名コンポーネントが含まれている場合、これらはパッケージの「views」ディレクトリ内の components ディレクトリに配置する必要があります(loadViewsFrom メソッドで指定されているように)。その後、パッケージのビューネームスペースをコンポーネント名の接頭辞としてレンダリングすることができます:

<x-courier::alert />

"About" Artisan コマンド

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

コマンド

Laravel にパッケージの Artisan コマンドを登録するには、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,
]);
}
}

公開アセット

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の2つの公開グループを定義するために、パッケージのサービスプロバイダーのbootメソッドでタグを使用しましょう:

    /**
* 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');
}

これで、ユーザーはvendor:publishコマンドを実行する際に、タグを参照してこれらのグループを個別に公開することができます:

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