ホームページ > 記事 > PHPフレームワーク > Laravel における依存関係注入と IoC の詳細な紹介 (例付き)
この記事では、Laravel での依存性注入と IoC について詳しく説明します (サンプル付き)。一定の参考価値があります。必要な友人は参照してください。お役に立てれば幸いです。
開発者として、私たちはデザイン パターンを使用したり、新しい堅牢なフレームワークを試したりすることで、適切に設計された堅牢なコードを作成する新しい方法を常に見つけようとしています。この記事では、Laravel の IoC コンポーネントを使用した依存性注入の設計パターンを調査し、それがどのように設計を改善できるかを見ていきます。
依存性注入
依存性注入という用語は、Martin Fowler によって提案された用語であり、アプリケーションにコンポーネントを注入する行為です。 Ward Cunningham 氏は次のように述べています:
依存性の注入はアジャイル アーキテクチャの重要な要素です。
例を見てみましょう:
class UserProvider{ protected $connection; public function __construct(){ $this->connection = new Connection; } public function retrieveByCredentials( array $credentials ){ $user = $this->connection ->where( 'email', $credentials['email']) ->where( 'password', $credentials['password']) ->first(); return $user; } }
このクラスをテストまたは保守したい場合は、データベースのインスタンスにアクセスしていくつかのクエリを実行する必要があります。これを回避するには、このクラスを他のクラスから 分離 することができます。Connection
クラスを直接使用せずに挿入する 3 つのオプションのいずれかがあります。
コンポーネントをクラスに挿入するときは、次の 3 つのオプションのいずれかを使用できます。
class UserProvider{ protected $connection; public function __construct( Connection $con ){ $this->connection = $con; } ...
同様に、 Setter メソッドを使用して依存関係を注入することもできます。
class UserProvider{ protected $connection; public function __construct(){ ... } public function setConnection( Connection $con ){ $this->connection = $con; } ...
interface ConnectionInjector{ public function injectConnection( Connection $con ); } class UserProvider implements ConnectionInjector{ protected $connection; public function __construct(){ ... } public function injectConnection( Connection $con ){ $this->connection = $con; } }
クラスがインターフェイスを実装するとき、依存関係を解決するために injectConnection
メソッドを定義します。
クラスをテストするときに、依存クラスをモックしてパラメーターとして渡すことができるようになりました。各クラスは特定のタスクに重点を置く必要があり、依存関係の解決には関心を持たないでください。こうすることで、より集中的で保守しやすいアプリケーションが作成されます。
DI についてさらに詳しく知りたい場合は、Alejandro Gervassio がこの連載記事で広範囲かつ専門的に取り上げていますので、必ずお読みください。では、IoCとは何でしょうか? IoC (制御の反転) では依存関係の注入を使用する必要はありませんが、依存関係を効果的に管理するのに役立ちます。
Ioc は、依存関係の解決を容易にする単純なコンポーネントです。オブジェクトをコンテナとして記述することができ、クラスが解決されるたびに依存関係が自動的に挿入されます。
Laravel Ioc は、オブジェクトをリクエストするときに依存関係を解決する方法が少し特殊です:
私たちは A を使用します。この記事では、簡単な例でそれを改善します。 SimpleAuth
クラスは FileSessionStorage
に依存するため、コードは次のようになります:
class FileSessionStorage{ public function __construct(){ session_start(); } public function get( $key ){ return $_SESSION[$key]; } public function set( $key, $value ){ $_SESSION[$key] = $value; } } class SimpleAuth{ protected $session; public function __construct(){ $this->session = new FileSessionStorage; } } //创建一个 SimpleAuth $auth = new SimpleAuth();
これは古典的なアプローチです。コンストラクター Function の使用から始めましょう。注射が始まります。
class SimpleAuth{ protected $session; public function __construct( FileSessionStorage $session ){ $this->session = $session; } }
次にオブジェクトを作成します:
$auth = new SimpleAuth( new FileSessionStorage() );
Laravel Ioc を使用してこれらすべてを管理したいと思います。
Application
クラスは Container
クラスを継承しているため、App
ファサードを通じてコンテナにアクセスできます。
App::bind( 'FileSessionStorage', function(){ return new FileSessionStorage; });
bind
メソッドの最初のパラメータはコンテナにバインドされる一意の ID で、2 番目のパラメータは FileSessionStorage## が実行されるたびに実行されるコールバック関数です。 # クラスが実行されますが、以下に示すようにクラス名を表す文字列を渡すこともできます。
注: Laravel パッケージを見ると、バインディングが ( view、
view.finder## など) のようにグループ化されていることがわかります。 # ...)。 セッション ストアを MySQL ストレージに変換すると仮定すると、クラスは次のようになります。
class MysqlSessionStorage{ public function __construct(){ //... } public function get($key){ // do something } public function set( $key, $value ){ // do something } }
依存関係を変更したので、
SimpleAuth も変更する必要があります。関数を構築し、新しいオブジェクトをコンテナにバインドします。 高レベルのモジュールは低レベルのモジュールに依存すべきではなく、両方とも抽象オブジェクトに依存する必要があります。
Robert C. MartinSimpleAuth
私たちの
クラスは、ストレージがどのように行われるかを気にする必要はなく、代わりにサービスの利用に重点を置く必要があります。 したがって、ストレージを抽象的に実装できます:
interface SessionStorage{ public function get( $key ); public function set( $key, $value ); }
これにより、
SessionStorage インターフェイスのインスタンスを実装して要求できます: <pre class="brush:php;toolbar:false">class FileSessionStorage implements SessionStorage{
public function __construct(){
//...
}
public function get( $key ){
//...
}
public function set( $key, $value ){
//...
}
}
class MysqlSessionStorage implements SessionStorage{
public function __construct(){
//...
}
public function get( $key ){
//...
}
public function set( $key, $value ){
//...
}
}
class SimpleAuth{
protected $session;
public function __construct( SessionStorage $session ){
$this->session = $session;
}
}</pre>
If
を使用して、コンテナを通じて SimpleAuth
クラスを解決します。コンテナは、問題を解決しようとして
BindingResolutionException
をスローします。バインディングからのクラス その後、リフレクション メソッドに戻り、すべての依存関係を解決します。 <pre class="brush:php;toolbar:false">Uncaught exception 'Illuminate\Container\BindingResolutionException' with message 'Target [SessionStorage] is not instantiable.'</pre>
コンテナはインターフェイスをインスタンス化しようとしています。このインターフェースに特定のバインディングを作成できます。
App:bind( 'SessionStorage', 'MysqlSessionStorage' );
これで、コンテナからこのインターフェイスを解決しようとするたびに、
MysqlSessionStorage インスタンスを取得します。ストレージ サービスを切り替えたい場合は、このバインディングを変更するだけです。 <p><strong>注:</strong> クラスがコンテナーにバインドされているかどうかを確認する場合は、<code>App::bound('ClassName')
を使用するか、# を使用できます。 ##App::bindIf('ClassName') まだ登録されていないバインディングを登録します。
App::singleton('ClassName', 'resolver') も提供します。
App::instance('ClassName', 'instance') を使用してシングルトン バインディングを作成することもできます。
コンテナが依存関係を解決できない場合、
ReflectionException がスローされますが、
App::resolveAny(Closure) メソッドを使用して、次の形式で指定された型を解決できます。コールバック関数。
注: 特定の型の解決メソッドを登録している場合、resolveAny メソッドは引き続き呼び出されますが、直接
bind# を返します。 # # メソッドの戻り値。 ヒント
, しかし、プロジェクトがどんどん大きくなると、サービスプロバイダーを利用する必要が出てきます。 テスト:
php Artisan tinker
の使用を検討できます。これは非常に強力で、Laravel テスト プロセスの改善に役立ちます。Reflection API:
PHP の Reflection API は非常に強力です。Laravel Ioc を詳しく知りたい場合は、Reflection API に精通している必要があります。詳細については、まずこのチュートリアルを読んでください。 [関連する推奨事項: PHP ビデオ チュートリアル
]以上がLaravel における依存関係注入と IoC の詳細な紹介 (例付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。