ホームページ > 記事 > PHPフレームワーク > laravel依存性注入とは何ですか
laravel 依存性注入という用語は、Martin Fowler によって提案された用語です。アプリケーションにコンポーネントを注入する動作です。依存性注入は、アジャイル アーキテクチャの重要な要素です。使用例は、「class UserProvider{保護された $connection...}"。
この記事の動作環境:Windows 7 System、Laravelバージョン5.7、Dell G3コンピューター。
laravel 依存関係注入とは何ですか?
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 も変更する必要があります。関数を構築し、新しいオブジェクトをコンテナにバインドします。
抽象化は詳細に依存すべきではなく、詳細は抽象化に依存する必要があります。SimpleAuth私たちの
Robert C. Martin
クラスは、ストレージがどのように行われるかを気にする必要はなく、代わりにサービスの利用に重点を置く必要があります。 したがって、ストレージを抽象的に実装できます:
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>
<p>如果我们使用 <code>App::make('SimpleAuth')
通过容器解析 SimpleAuth
类,容器将会抛出 BindingResolutionException
,尝试从绑定解析类之后,返回到反射方法并解析所有依赖项。
Uncaught exception 'Illuminate\Container\BindingResolutionException' with message 'Target [SessionStorage] is not instantiable.'
容器正试图将接口实例化。我们可以为该接口做一个具体的绑定。
App:bind( 'SessionStorage', 'MysqlSessionStorage' );
现在每次我们尝试从容器解析该接口时,我们会得到一个 MysqlSessionStorage
实例。如果我们想要切换我们的存储服务,我们只要变更一下这个绑定。
Note: 如果你想要查看一个类是否已经在容器中被绑定,你可以使用 App::bound('ClassName')
,或者可以使用 App::bindIf('ClassName')
来注册一个还未被注册过的绑定。
Laravel Ioc 也提供 App::singleton('ClassName', 'resolver')
来处理单例的绑定。
你也可以使用 App::instance('ClassName', 'instance')
来创建单例的绑定。
如果容器不能解析依赖项就会抛出 ReflectionException
,但是我们可以使用 App::resolvingAny(Closure)
方法以回调函数的形式来解析任何指定的类型。
Note: 如果你为某个类型已经注册了一个解析方式 resolvingAny
方法仍然会被调用,但它会直接返回 bind
方法的返回值。
这些绑定写在哪儿:
如果只是一个小型应用你可以写在一个全局的起始文件 global/start.php
中,但如果项目变得越来越庞大就有必要使用 Service Provider 。
测试:
当需要快速简易的测试可以考虑使用 php artisan tinker
,它十分强大,且能帮你提升你的 Laravel 测试流程。
Reflection API:
PHP 的 Reflection API 是非常强大的,如果你想要深入 Laravel Ioc 你需要熟悉 Reflection API ,可以先看下这个 教程 来获得更多的信息。
相关推荐:最新的五个Laravel视频教程
以上がlaravel依存性注入とは何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。