以下に、接続が 1 つしかない場合にデータベース アクセスを簡素化するための 3 つのオプションを示します (これは、私が取り組んでいる Web アプリの場合によくあります)。
一般的な考え方は、スクリプトが最初にクエリを実行したときに接続し、スクリプトが終了するまで接続を維持するように、DB 接続を透過的にすることです。
どれが一番良いと思うか、その理由を知りたいです。これらに適合する可能性のあるデザインパターンの名前がわからないので、使用しないで申し訳ありません。また、PHP5 でこれを行うためのより良い方法があれば、共有してください。
簡単に紹介すると、クエリ メソッドを含む DB_Connection クラスがあります。これは、私が制御できないサードパーティ クラスであり、この例の目的のためにインターフェイスを単純化しました。各オプションでは、状況を説明するために架空の DB「アイテム」テーブルのモデル例も提供しました。
オプション 3 は、私が最も気に入っているインターフェイスを提供してくれるものですが、残念ながら実用的ではないと思います。
以下のコメント ブロックで、それぞれの長所と短所 (私が見ることができる) について説明しました。
現時点では、モデルではなく DB ラッパー クラスに負担がかかるため、オプション 1 に傾いています。
すべてのコメントに感謝します!
注: 何らかの理由で、スタック オーバーフロー プレビューにアンダースコアではなく、エンコードされた HTML エンティティが表示されます。投稿がそのように通過する場合は、これを考慮してください。
<?php
/**
* This is the 3rd-party DB interface I'm trying to wrap.
* I've simplified the interface to one method for this example.
*
* This class is used in each option below.
*/
class DB_Connection {
public function &query($sql) { }
}
/**
* OPTION 1
*
* Cons: Have to wrap every public DB_Connection method.
* Pros: The model code is simple.
*/
class DB {
private static $connection;
private static function &getConnection() {
if (!self::$connection) {
self::$connection = new DB_Connection();
}
return self::$connection;
}
public static function &query($sql) {
$dbh = self::getConnection();
return $dbh->query($sql);
}
}
class Item {
public static function &getList() {
return DB::query("SELECT * FROM items");
}
}
/**
* OPTION 2
*
* Pros: Don't have to wrap every DB_Connection function like in Option 1
* Cons: Every function in the model is responsible for checking the connection
*/
class DB {
protected static $connection = null;
public function connect() {
self::$connection = new DB_Connection();
}
}
class Item extends DB {
public static function &getList() {
if (!self::$connection) $this->connect();
return self::$connection->query("SELECT * FROM items");
}
}
/**
* OPTION 3
*
* Use magic methods
*
* Pros: Simple model code AND don't have to reimplement the DB_Connection interface
* Cons: __callStatic requires PHP 5.3.0 and its args can't be passed-by-reference.
*/
class DB {
private static $connection = null;
public static function &getConnection() {
if (!self::$connection) {
self::$connection = new DB_Connection();
}
return self::$connection;
}
public static function __callStatic($name, $args) {
if (in_array($name, get_class_methods('DB_Connection'))) {
return call_user_func_array(
array(self::getConnection(), $name), $args);
}
}
}