— y2sunlight 2020-07-29
目次
Apricotでは、DIコンテナーに League/Container を使用しています。Apricotのスケルトンでは、League/Container のサービスプロバイダー機能を利用して、サービス(またはモデルなどのクラスも含まれる)を登録することができます。サービスはアプリレーション全体で共有できます。即ちシングルトンとして利用できます。
DIコンテナを使用することで、サービスとその依存関係を登録しておいて後で取得することができます。例えば、サービスAがモデルBとモデルCを使用しているような場合、サービスコンテナにサービスAを要求すると、自動的にモデルBとCを生成し、それらをサービスAのコンストラクタに与えてサービスAを生成してくれます。これがDIコンテナです。
ここでは、League/Container の慣例に従いDIコンテナと呼んでいますが、これはサービスコンテナと呼ばれることもあります。
サービスプロバイターは、アプリケーション内の全てのDIコンテナを登録し整理する方法を提供してくれます。また、サービスプロバイダーではサービスが取得された時点で遅延登録されるため、アプリケーションのパフォーマンス向上にも寄与します。
Apricotのスケルトンではサービスプロバイターとして、League/Container が提供している基本サービスプロバイダークラス( AbstractServiceProvider
)を拡張した App\Provider
クラスを定義しています。このクラスは、/your-project/app
に配置されています。
以下にApricotのスケルトンで初期実装されているProviderクラスの抜粋を示します。
/your-project/app
<?php namespace App; use League\Container\ServiceProvider\AbstractServiceProvider; /** * Provider class for service */ class Provider extends AbstractServiceProvider { /** * 提供される配列は、サービスがこのサービスプロバイダーによって提供されていることをコンテナーに知らせるための方法です。 * このサービスプロバイダーを介して登録されるすべてのサービスには、この配列にエイリアスが追加されている必要があります。 * そうでない場合は無視されます。 * * @var array */ protected $provides = [ // Sample 'SampleService', ]; /** * ここでマジックが起こります。メソッド内でコンテナーにアクセスして必要なものを登録または取得できますが、 * このメソッド内に登録されたすべてのエイリアスは '$provides' 配列で宣言する必要があります。 */ public function register() { // Sample $this->getContainer() ->add('SampleService', \App\Services\SampleService::class, true) ->addArgument('User') ; $this->getContainer()->add('User', \App\Models\User::class); } }
スケルトンではサービスのサンプルとして SampleService
クラスを提供しています。このクラスはコンストラクタにUser
モデルを与えて作ります。
SampleService
クラスをサービスプロバイターに登録するには、コンテナのadd()
メソッドを使用し、その引数は、エイリアス名、登録するクラス、そして共有フラグです。共有フラグがtrueの場合、このクラスはシングルトンとして動作します。addArgument()
メソッドは登録するクラスのコンストラクタに与える引数を定義します。この引数もまたadd()
メソッドで登録しておく必要があります。
サービス(またはモデル)をサービスプロバイターに登録する場合は、上例に習って適宜追加して下さい。League/Container のサービスプロバイダーについての詳細はこちらをご覧ください。
サービスプロバイダーで登録したサービス(またはモデル)を取得するには、App\Foundation\Container
クラスを使用します。このクラスは、\League\Container\Container
をシングルトンにしたもので、以下のメソッドがあります。これらのメソッドは PSR-11 に準拠しています。
使用法: Container::{メソッド}
メソッド | 機能 |
---|---|
mixed get(string $id) | 識別子idでコンテナのエントリを検索して返します。 |
bool has(string $id) | コンテナが指定された識別子idのエントリを返すことができる場合はtrueを返します。 |
スタブコントローラのindexアクションには、DIコンテナの使用例があります。
/your-project/app/Controllers
public function index(int $no=null) { $title = "Stub {$no}"; /** * @var \App\Services\SampleService $service */ $service = Container::get('SampleService'); $count = $service->getUserCount(); $messages[] = "Number of registered users : {$count}"; return render('stub',['title'=>$title,'messages'=>$messages]); }
Container
シングルトンの get()
メソッドで、サービスプロバイダーでシングルトンとして登録した SampleService
のインスタンスを取得します。このインスタンスはアプリケーション全体で共有されます。