0

MVC を PDO を使用するように切り替えています (わかっていますが、期限切れです)。私のアプリケーションは、過去に次のクラス階層を使用していました。

データベース.クラス>メイン.クラス>ユーザー.クラス

(それぞれが他を拡張します)。ただし、オブジェクトが作成される前に、mysql 接続が確立されています (mysql_connect)。接続が開かれると、すべてのクエリが実行されるラッパー クラスとして Database.class を使用できます。拡張により、「クエリ」関数 ($this->query) を呼び出すだけで、User.class 内のクエリを作成できます。

PDO を使用して、プロセスを模倣しようとしましたが、エラーが見つかりました。Database.class にシングルトン関数を作成しました。

function __construct()
{
    $this->db = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8', DB_USER, DB_PASSWORD);
    $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $this->db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}

public static function getInstance()
{
    if (!isset(self::$instance)){
        $object = __CLASS__;
        self::$instance = new $object;
    }
    return self::$instance;
}

function query($qry,$params=NULL){
    $qry = $this->db->prepare('SELECT * FROM users WHERE userID = :userID');
    $qry->execute(array(':userID' => 1));
    $results = $qry->fetchAll(PDO::FETCH_ASSOC);
    return $results;
}

次に Main.class でインスタンスを取得します。

function __construct()
{
    $this->db = parent::getInstance();
}

だから User.class で私は呼び出そうとします

function __construct(){
    parent::__construct();
}
function test(){
    return $this->db->query("test");
}

したがって、Main.class オブジェクトから任意のクエリを正常に実行できます。しかし、User.class オブジェクトからクエリを実行しようとすると、次のエラーが表示されます。 $db in Main from User.class (User オブジェクトの作成時に Main のコンストラクターを呼び出します)。問題の一部は、Main.class が独自のオブジェクトとしてアプリケーションの早い段階で作成されることです。私は、PDO の 2 つのインスタンスが作成されると考えています。データベース.クラス)

だから私の質問は、これを実現する方法はありますか? または、作成するすべてのオブジェクトにインジェクションを使用し (一部のスクリプトには Main.class を拡張する複数のオブジェクトが組み込まれているため、毎回 PDO のインスタンスを作成しようとするため)、pdo オブジェクトをコンストラクターに渡すのが最善のオプションですか? 私はむしろそれを行う必要はありません (マークアップが少ないほど良い) では、別のオプションは、すべてのクラスが使用する STATIC 変数を使用することでしょうか? 最良の方法は何ですか?(これが紛らわしい場合はお知らせください)

これにインジェクションを使用している人を見てきました。また、pdo ラッパー クラスを拡張する例を見てきました (ただし、1 回だけです)。

ありがとう!(私はスタックオーバーフローが大好きです!)

4

1 に答える 1

1

これらのいずれかでデータベース クラスを拡張する必要はありません。これは、基本的にインスタンスを 1 つしか持つことができないすべてのシングルトンになるためです...代わりにデータベース クラスを使用させたいと考えています。したがって、最も抽象的な db メソッドを に配置しDatabase、次に特定のものに対するクエリを作成するメソッドを に配置しUserます。これは、Database実際にラップすることを意味し、PDO他のすべてのクラスが db 操作で使用するものです。Mainまたはクラスは、Baseアクティブなレコードなどを実装しようとしている場合を除き、必要ない場合もあります。

class Database {
   static protected $instance;

   /**
    * @var PDO
    */
   protected $connection;

   protected function __construct($dsn, $user, $pass, $attrs = array()) {
       // create pdo instance and assign to $this->pdo
   }

   public static function getInstance() {
       if(!self::$instance) {
           // get the arguments to the constructor from configuration somewhere
           self::$instance = new self($dsn, $user, $pass);
       }

       return self::$instance;
   }

   // proxy calls to non-existant methods on this class to PDO instance
   public function __call($method, $args) {
       $callable = array($this->pdo, $method);
       if(is_callable($callable)) {
           return call_user_func_array($callable, $args);
       }
   }
}

class Main {
   protected $db;

   public function __construct() {
      $this->db = Database::getInstance();
   }   
}

    class User extends Main{

       public function __construct() {
            parent::__construct();
       }

       public function findById($id) {
           $qry = $this->db->prepare('SELECT * FROM users WHERE userID = :userID');
           $qry->execute(array(':userID' => $id));
           $results = $qry->fetchAll(PDO::FETCH_ASSOC);

           return $results
       }
    }
于 2013-08-07T00:11:33.237 に答える