ホームページ > PHPフレームワーク > Laravel > Laravel の依存性注入と IoC

Laravel の依存性注入と IoC

Guanhui
リリース: 2020-06-15 17:57:37
転載
2679 人が閲覧しました

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 メソッド注入

#同様に、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

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 パッケージを見ると、バインディングが ( viewview.finder## など) のようにグループ化されていることがわかります。 # ...)。 セッション ストアを MySQL ストレージに変換すると仮定すると、クラスは次のようになります。

class MysqlSessionStorage{

  public function __construct(){
    //...
  }

  public function get($key){
    // do something
  }

  public function set( $key, $value ){
    // do something
  }
}
ログイン後にコピー

依存関係を変更したので、

SimpleAuth

も変更する必要があります。関数を構築し、新しいオブジェクトをコンテナにバインドします。

高レベルのモジュールは低レベルのモジュールに依存すべきではなく、両方とも抽象オブジェクトに依存する必要があります。
抽象化は詳細に依存すべきではなく、詳細は抽象化に依存する必要があります。


Robert C. Martin

私たちの
SimpleAuth

クラスは、ストレージがどのように行われるかを気にする必要はなく、代わりにサービスの利用に重点を置く必要があります。 したがって、ストレージを抽象的に実装できます:

interface SessionStorage{
  public function get( $key );
  public function set( $key, $value );
}
ログイン後にコピー

これにより、

SessionStorage

インターフェイスのインスタンスを実装して要求できます: <div class="code" style="position:relative; padding:0px; margin:0px;"><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-&gt;session = $session;   } }</pre><div class="contentsignin">ログイン後にコピー</div></div>If

App::make('SimpleAuth')

を使用して、コンテナを通じて SimpleAuth クラスを解決します。コンテナは、問題を解決しようとして BindingResolutionException
をスローします。バインディングからのクラス その後、リフレクション メソッドに戻り、すべての依存関係を解決します。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">Uncaught exception 'Illuminate\Container\BindingResolutionException' with message 'Target [SessionStorage] is not instantiable.'</pre><div class="contentsignin">ログイン後にコピー</div></div>コンテナはインターフェイスをインスタンス化しようとしています。このインターフェースに特定のバインディングを作成できます。

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 Ioc 仅仅只是一个文件,不会花费你太多时间来完成所有功能。你想了解更多关于 Laravel Ioc 或者 Ioc 的一般情况吗?那请告诉我们吧!

推荐教程:《Laravel教程

以上がLaravel の依存性注入と IoCの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:learnku.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート