3

静的クラスは、他のプロジェクトでコードを使用できなくする依存関係を挿入し、単体テストを許可しないため、静的クラスを避けるように何度も耳にしました。

class DBデータベースにアクセスするための一般的な方法があるとしましょう。そのようなクラスの場合static、コード内のどこからでも呼び出すことができます。

DB::execQuery(...);

ただし、これにより依存関係が作成されるため、DBクラスを静的ではないようにします。このような場合、コードのどこかに次のようになります。

$db = new DB();

次に、コードを呼び出すことができます

$db->execQuery(...);

しかし今、$db内部を使用するとき、function私たちは毎回最初にそれをこのように宣言する必要があります

global $db;

これを回避する方法はありますか?

1つの方法は、$dbオブジェクトを使用するクラスにオブジェクトを注入することですが、それを使用するすべてのクラスにオブジェクトを注入する必要があります。これはばかげています。静的クラスは、操作がはるかに高速で、記述するコードが少なくなります。私は何かが足りないのですか?!

4

2 に答える 2

5

$ dbは、インスタンス化時にプロパティに挿入される可能性があります。その場合、各メソッドに渡すのではなく、このプロパティにアクセスするだけで済みます。

class MyClass {
  protected $_db; // DB Connection
  public function __construct($db) {
    $this->_db = $db;
  }

  public function foo() {
    $this->_db->query('...');
  }

}

それを超えて、グローバル変数のように動作しようとするが、テストの問題のいくつかを解決するサービスコンテナ(別名依存性注入コンテナ)を持つことを検討できます。これらの関連する質問のいくつかを見てください

DIコンテナがあると、のようなクラスで静的メソッドを使用できますDI_Container::get('db')。これは、他の静的呼び出しの一部とよく似ていglobalますが、この場合、DI_Containerテストやその他の状況で追加のアクションを実行できるようにする特別なメソッドが含まれています。グローバルの「悪」の一部を排除します。

于 2012-05-07T17:15:57.523 に答える
1

Mike B の回答に加えて、あなたのコードの間違った設計は次のとおりであることを指摘したいと思います。

実際には、データベースはモデル、またはデータベースについて知る必要があるアプリケーションの小さな部分でのみ使用する必要があります。したがって、これらのクラスはデータベースがあることを認識し、それを依存関係として使用する必要があります (Mike B が言ったように、コンストラクターを介して渡されます)。

ただし、アプリケーションの残りの部分はデータベースを気にする必要はなく、モデルのみを気にする必要があります。データベースにアクセスするすべてのコードを Model クラスにリファクタリングして収集することに集中してください。

このように、アプリケーションには、依存関係を持つモデル層があります: データベース オブジェクト/接続。そして、アプリケーションの残りの部分はモデルを使用します。モデルで何が起こっても、コントローラー/ビュー ビジネスは関係ありません。

リファクタリングをお楽しみください。

于 2014-01-28T08:51:22.017 に答える