コンテンツへスキップ

パッケージ開発

導入

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

リソース

設定

通常、パッケージの設定ファイルをアプリケーションの`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');
exclamation

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

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

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

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

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

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

ルート

パッケージにルートが含まれている場合は、`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`構文規則を使用して参照されます。そのため、`messages`ファイルから`courier`パッケージの`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」ディレクトリ(loadViewsFromメソッドで指定)のcomponentsディレクトリに配置する必要があります。その後、パッケージのビュー名前空間をコンポーネント名の前に付けることで、それらをレンダリングできます。

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

コマンド

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

コマンドの最適化

Laravelのoptimizeコマンドは、アプリケーションの構成、イベント、ルート、ビューをキャッシュします。optimizesメソッドを使用して、optimizeコマンドとoptimize:clearコマンドが実行されたときに呼び出す必要があるパッケージ独自のArtisanコマンドを登録できます。

/**
* Bootstrap any package services.
*/
public function boot(): void
{
if ($this->app->runningInConsole()) {
$this->optimizes(
optimize: 'package:optimize',
clear: 'package:clear-optimizations',
);
}
}

公開アセット

パッケージには、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パッケージの2つの公開グループ(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->publishesMigrations([
__DIR__.'/../database/migrations/' => database_path('migrations')
], 'courier-migrations');
}

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

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