パッケージ開発¶
はじめに¶
パッケージは、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
セクションにパッケージ名をリストすることができます:
アプリケーションのdont-discover
ディレクティブ内で*
文字を使用して、すべてのパッケージの発見を無効にすることもできます:
サービスプロバイダ¶
サービスプロバイダは、パッケージとLaravelの接続点です。サービスプロバイダは、Laravelのサービスコンテナにバインドし、パッケージのリソース(ビュー、設定、言語ファイルなど)をロードする場所をLaravelに通知する役割を担います。
サービスプロバイダはIlluminate\Support\ServiceProvider
クラスを拡張し、register
とboot
の2つのメソッドを含みます。ベースのServiceProvider
クラスはilluminate/support
Composerパッケージにあり、独自のパッケージの依存関係に追加する必要があります。サービスプロバイダの構造と目的について詳しくは、そのドキュメントを参照してください。
リソース¶
設定¶
通常、パッケージの設定ファイルをアプリケーションのconfig
ディレクトリに公開する必要があります。これにより、パッケージのユーザーはデフォルトの設定オプションを簡単にオーバーライドできます。設定ファイルを公開できるようにするには、サービスプロバイダのboot
メソッドからpublishes
メソッドを呼び出します:
/**
* パッケージサービスのあらゆる初期化処理を行う。
*/
public function boot(): void
{
$this->publishes([
__DIR__.'/../config/courier.php' => config_path('courier.php'),
]);
}
これで、パッケージのユーザーがLaravelのvendor:publish
コマンドを実行すると、ファイルが指定された公開場所にコピーされます。設定が公開されると、その値は他の設定ファイルと同様にアクセスできます:
$value = config('courier.option');
Warning
設定ファイルにクロージャを定義してはいけません。ユーザーがconfig:cache
Artisanコマンドを実行すると、正しくシリアライズできません。
デフォルトのパッケージ設定¶
独自のパッケージ設定ファイルをアプリケーションの公開されたコピーとマージすることもできます。これにより、ユーザーは設定ファイルの公開されたコピーで実際にオーバーライドしたいオプションのみを定義できます。設定ファイルの値をマージするには、サービスプロバイダのregister
メソッド内でmergeConfigFrom
メソッドを使用します。
mergeConfigFrom
メソッドは、パッケージの設定ファイルへのパスを最初の引数として受け取り、アプリケーションの設定ファイルの名前を2番目の引数として受け取ります:
/**
* アプリケーションサービスの登録。
*/
public function register(): void
{
$this->mergeConfigFrom(
__DIR__.'/../config/courier.php', 'courier'
);
}
Warning
このメソッドは設定配列の最初のレベルのみをマージします。ユーザーが多次元設定配列を部分的に定義した場合、不足しているオプションはマージされません。
ルート¶
パッケージにルートが含まれている場合、loadRoutesFrom
メソッドを使用してそれらをロードできます。このメソッドは、アプリケーションのルートがキャッシュされているかどうかを自動的に判断し、ルートが既にキャッシュされている場合はルートファイルをロードしません:
/**
* パッケージサービスのあらゆる初期化処理を行う。
*/
public function boot(): void
{
$this->loadRoutesFrom(__DIR__.'/../routes/web.php');
}
マイグレーション¶
パッケージにデータベースマイグレーションが含まれている場合、publishesMigrations
メソッドを使用して、指定されたディレクトリまたはファイルにマイグレーションが含まれていることをLaravelに通知できます。Laravelがマイグレーションを公開すると、ファイル名内のタイムスタンプが現在の日付と時刻に自動的に更新されます:
/**
* パッケージサービスのあらゆる初期化処理を行う。
*/
public function boot(): void
{
$this->publishesMigrations([
__DIR__.'/../database/migrations' => database_path('migrations'),
]);
}
言語ファイル¶
パッケージに言語ファイルが含まれている場合、loadTranslationsFrom
メソッドを使用してLaravelにそれらをロードする方法を通知できます。たとえば、パッケージがcourier
という名前の場合、サービスプロバイダのboot
メソッドに次のように追加する必要があります:
/**
* パッケージサービスのあらゆる初期化処理を行う。
*/
public function boot(): void
{
$this->loadTranslationsFrom(__DIR__.'/../lang', 'courier');
}
パッケージの翻訳行は、package::file.line
構文規則を使用して参照されます。したがって、courier
パッケージのmessages
ファイルからwelcome
行を次のようにロードできます:
echo trans('courier::messages.welcome');
loadJsonTranslationsFrom
メソッドを使用して、パッケージのJSON翻訳ファイルを登録することもできます。このメソッドは、パッケージのJSON翻訳ファイルを含むディレクトリへのパスを受け取ります:
/**
* パッケージサービスのあらゆる初期化処理を行う。
*/
public function boot(): void
{
$this->loadJsonTranslationsFrom(__DIR__.'/../lang');
}
言語ファイルの公開¶
パッケージの言語ファイルをアプリケーションのlang/vendor
ディレクトリに公開したい場合は、サービスプロバイダのpublishes
メソッドを使用できます。publishes
メソッドは、パッケージパスとその希望する公開場所の配列を受け取ります。たとえば、courier
パッケージの言語ファイルを公開するには、次のようにします:
/**
* パッケージサービスのあらゆる初期化処理を行う。
*/
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
メソッドに以下を追加します:
/**
* パッケージサービスのブートストラップ
*/
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
メソッドは、パッケージビューパスとその希望する公開場所の配列を受け取ります:
/**
* パッケージサービスのブートストラップ
*/
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コンポーネントを利用するパッケージを構築している場合、またはコンポーネントを非標準的なディレクトリに配置している場合、Laravelがコンポーネントを見つける場所を知るために、コンポーネントクラスとそのHTMLタグエイリアスを手動で登録する必要があります。通常、パッケージのサービスプロバイダのboot
メソッドでコンポーネントを登録する必要があります:
use Illuminate\Support\Facades\Blade;
use VendorPackage\View\Components\AlertComponent;
/**
* パッケージサービスのブートストラップ
*/
public function boot(): void
{
Blade::component('package-alert', AlertComponent::class);
}
コンポーネントが登録されると、そのタグエイリアスを使用してレンダリングできます:
パッケージコンポーネントの自動読み込み¶
または、componentNamespace
メソッドを使用して、規約に従ってコンポーネントクラスを自動読み込みすることもできます。例えば、Nightshade
パッケージにはCalendar
とColorPicker
コンポーネントがあり、これらはNightshade\Views\Components
名前空間内にあります:
use Illuminate\Support\Facades\Blade;
/**
* パッケージサービスのブートストラップ
*/
public function boot(): void
{
Blade::componentNamespace('Nightshade\\Views\\Components', 'nightshade');
}
これにより、package-name::
構文を使用してベンダー名前空間でパッケージコンポーネントを使用できます:
Bladeは、コンポーネント名をパスカルケースにして、このコンポーネントにリンクされたクラスを自動的に検出します。サブディレクトリも「ドット」記法でサポートされています。
匿名コンポーネント¶
パッケージに匿名コンポーネントが含まれている場合、それらはパッケージの「ビュー」ディレクトリのcomponents
ディレクトリ内に配置する必要があります(loadViewsFrom
メソッドで指定されたとおり)。その後、パッケージのビュー名前空間をプレフィックスとして付けてレンダリングできます:
"About" Artisanコマンド¶
Laravelの組み込みabout
Artisanコマンドは、アプリケーションの環境と設定の概要を提供します。パッケージはAboutCommand
クラスを介してこのコマンドの出力に追加情報をプッシュできます。通常、この情報はパッケージサービスプロバイダのboot
メソッドから追加されます:
use Illuminate\Foundation\Console\AboutCommand;
/**
* アプリケーションサービスのブートストラップ
*/
public function boot(): void
{
AboutCommand::add('My Package', fn () => ['Version' => '1.0.0']);
}
コマンド¶
パッケージのArtisanコマンドをLaravelに登録するには、commands
メソッドを使用できます。このメソッドはコマンドクラス名の配列を期待します。コマンドが登録されると、Artisan CLIを使用して実行できます:
use Courier\Console\Commands\InstallCommand;
use Courier\Console\Commands\NetworkCommand;
/**
* パッケージサービスのブートストラップ
*/
public function boot(): void
{
if ($this->app->runningInConsole()) {
$this->commands([
InstallCommand::class,
NetworkCommand::class,
]);
}
}
公開アセット¶
パッケージには、JavaScript、CSS、画像などのアセットが含まれている場合があります。これらのアセットをアプリケーションのpublic
ディレクトリに公開するには、サービスプロバイダのpublishes
メソッドを使用します。この例では、関連するアセットのグループを簡単に公開できるように、public
アセットグループタグも追加します:
/**
* パッケージサービスのブートストラップ
*/
public function boot(): void
{
$this->publishes([
__DIR__.'/../public' => public_path('vendor/courier'),
], 'public');
}
これで、パッケージのユーザーがvendor:publish
コマンドを実行すると、アセットが指定された公開場所にコピーされます。パッケージが更新されるたびにアセットを上書きする必要があるため、--force
フラグを使用できます:
ファイルグループの公開¶
パッケージのアセットとリソースのグループを個別に公開したい場合があります。例えば、パッケージの設定ファイルを公開させたいが、パッケージのアセットを公開させたくない場合があります。これを行うには、パッケージのサービスプロバイダからpublishes
メソッドを呼び出す際に「タグ」を付けます。例えば、courier
パッケージのサービスプロバイダのboot
メソッドで、2つの公開グループ(courier-config
とcourier-migrations
)を定義します:
/**
* パッケージサービスのブートストラップ
*/
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
コマンドを実行する際にタグを参照することで、これらのグループを個別に公開できます: