ホームページ >バックエンド開発 >PHPチュートリアル >PHP の依存関係の挿入と制御の反転の解析

PHP の依存関係の挿入と制御の反転の解析

巴扎黑
巴扎黑オリジナル
2017-08-08 13:55:442728ブラウズ

この記事では、PHP の依存性注入 (DI) と制御の反転 (IoC) に関する関連情報を主に紹介します。興味のある方は参考にしてください。

まず、依存性の注入と制御の反転について説明します。これも同じで、プログラム間の結合を減らすために使用されるデザイン パターンです。少し調べてみたところ、TP の公式 Web サイトに関連する記事がなかったので、これを紹介するためにこのささやかな記事を書きました。デザインパターンを見て、TP コミュニティに何か貢献できればと思っています。

まず第一に、このデザインパターンの定義を追求しないでください。そうしないと、著者はこれに深く影響を受けており、そのすべてが説明されています。理論的な観点から見ると、Java コードで記述されている語彙も馴染みのないものが多くあります。

何はともあれ、ようやく PHP の観点から依存性注入の概念を説明しましょう。

まず、ここにデータベース接続を使用する必要があるクラスがあると仮定します。最も原始的な方法によれば、このクラスを次のように記述できます。関数には、まずデータベース クラス ファイルを含めます。その後、新しい Db を通じて db クラスをインスタンス化し、データベース接続情報を渡します。その後、getList メソッドは $this->_db を通じてデータベース クラスを呼び出してデータベースを実装します。オペレーション。

目的の機能を達成できたようですが、これは悪夢の始まりです。example1、example2、example3... すべてが記述されると、ますます多くのクラスが db コンポーネントを使用する必要があります。このように、ある日、データベースのパスワードが変更されたり、db クラスが変更されたりした場合、すべてのクラス ファイルに戻って変更する必要があるのではないでしょうか。

この問題を解決するために、Factory メソッドを作成し、Factory::getDb() メソッドを通じて db コンポーネントのインスタンスを取得しました。

class example {
  
  private $_db;
  function __construct(){
    include "./Lib/Db.php";
    $this->_db = new Db("localhost","root","123456","test");
  }
  function getList(){
    $this->_db->query("......");//这里具体sql语句就省略不写了
  }
 }

サンプル クラスは次のようになります。



rreee

これは完璧ですか?今後のすべてのクラス (example1、example2、example3...) についてもう一度考えてみましょう。実際には、コンストラクターの Factory::getDb(); を通じて Db インスタンスを取得する必要があります。この結合は、Factory クラスとの結合になります。ファクトリ クラスは、データベースの接続情報をパッケージ化するのに役立つだけですが、データベース情報が変更されたときは、Factory::getDb() メソッドを変更するだけで済みます。しかし、ある日突然、ファクトリ メソッドが変更されます。名前を変更する必要がある、または getDb メソッドの名前を変更する必要がある場合、どうすればよいでしょうか?もちろん、この種の要求は実際には非常に混乱していますが、場合によってはこのような状況が存在します。 1 つの解決策は次のとおりです。


外部からのインジェクションに依存します。ということですか?次の例を見てください:


class Factory {
  public static function getDb(){
    include "./Lib/Db.php";
    return new Db("localhost","root","123456","test");
  }
 }

このように、サンプル クラスは外部クラスから完全に分離されており、Db クラスにはファクトリ メソッドや Db クラスが存在しないことがわかります。外部からサンプル クラスの setDb メソッドを呼び出して、接続インスタンスを直接挿入します。このように、この例では、db 接続がどのように生成されるかを気にする必要がありません。
これは依存関係注入と呼ばれます。実装はコード内に依存関係を作成しませんが、それをパラメーターとして渡します。これにより、プログラムの保守が容易になり、プログラム コードの結合度が低減され、疎結合が実現されます。

これはまだ終わっていません。サンプル クラスで db に加えて他の外部クラスが使用されていると仮定しましょう。疲れていますか?
わかりました、毎回非常に多くの行のコードを記述する必要がないように、別のファクトリ メソッドを作成しました:


class example {
  
  private $_db;
  function __construct(){
    $this->_db = Factory::getDb();
  }
  function getList(){
    $this->_db->query("......");//这里具体sql语句就省略不写了
  }
 }

例をインスタンス化すると、次のようになります:



class example {
  private $_db;
  function getList(){
    $this->_db->query("......");//这里具体sql语句就省略不写了
  }
  //从外部注入db连接
  function setDb($connection){
    $this->_db = $connection;
  }
 }
 //调用
$example = new example();
$example->setDb(Factory::getDb());//注入db连接
$example->getList();

It完璧に思えますが、上記のファクトリーメソッドを初めて使用したときの状態に戻ったように感じるのはなぜですか?これは確かに良い解決策ではないため、別の概念であるコンテナ (IoC コンテナや DI コンテナとも呼ばれます) が提案されています。


当初は setXXX メソッドを通じてさまざまなクラスを注入していました。コードは非常に長く、多くのメソッドが存在します。ただし、これはあまりクールではありません。setXXX メソッドは必要ありません。そのため、ファクトリ メソッドは必要ありません。 2. パッケージ化したら、依存関係の注入をどのように実装すればよいでしょうか?

ここで規約を紹介します。次のように、例のクラスのコンストラクターに Di $di という名前のパラメーターを渡します。



$example->setDb(Factory::getDb());//注入db连接
$example->setFile(Factory::getFile());//注入文件处理类
$example->setImage(Factory::getImage());//注入Image处理类
 ...

Di は、いわゆるコンテナーであり、さまざまなものを保存します。 Type インスタンスを使用する場合、$di->set() を通じて db という名前のインスタンスを設定します。これはコールバック関数を通じて渡されるため、db クラスは設定されたときにのみインスタンス化されます。 $di->get('db') が実行されるときも同様に、シングルトン モードを di クラスの設計に統合することもできます。


このように、グローバル スコープで Di クラスを宣言し、注入する必要があるすべてのクラスをコンテナーに配置し、そのコンテナーをコンストラクターのパラメーターとして example に渡すだけで済みます。サンプルクラスのコンテナからインスタンスを取得できます。もちろん、コンストラクターである必要はありません。setDi(Di $di) メソッドを使用して Di コンテナーに渡すこともできます。つまり、合意は自分で行うものなので、自分で理解する必要があります。 。

依存性注入と主要なコンテナーの概念が導入されたので、残っているのはそれを実際に使用して理解することだけです。

以上がPHP の依存関係の挿入と制御の反転の解析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。