電子書籍の厳選無料作品が豊富!

PHPでデータベースへのアクセスでMDB2を使っています。
よくpearのライブラリを継承して使うのですが、MDB2の場合下記(1)のようにインスタンスを作らない仕組みなのでしょうか?
(2)のようにMDB2を継承させて使うにはどのようにしたらよいのでしょうか?

(1)
$mdb2 =& MDB2::factory(CONFIG_DB_DSN);
$res =& $mdb2->query("SELECT * FROM users LIMIT 5");

(2)
$hoge = new hoge;
$res =& $hoge->query("SELECT * FROM users LIMIT 5");

class hoge extends MDB2 {
function query() {
echo "オーバーライドされない";
}
}

誰がご存じの方いらっしゃれば、ご教示いただければ幸いです。

A 回答 (2件)

(1)のパターンを、GoFデザインパターン「FactoryMethod」と呼びます。


factory()メソッドは、渡されたパラメータにより、戻り値とする『インスタンス化
されたオブジェクト』を切り替えます。
インスタンス化はfactory()を行った時点でされます。
よって、(2)のような明示的なインスタンス化は不要となります。

その上で、MDB2はMySql、PostgreSQL、SQLiteなどいろんなDBに対応しているようです。
色んなDBに対応するということは、操作が一緒でないと困ります。
なぜならDBが変わった途端に今まで作った操作が水の泡になっては問題だからです。
そこで、GoFデザインパターン「AbstractFactory」が利用されています。
それを利用する事で、「FactoryMethod」で受け取った戻り値は利用者には何のクラスの
オブジェクトなのかは不明ですが、どのクラスのオブジェクトだとしても以降の
呼び出すメソッドや手順が全く一緒となります。
MDB2を詳しく使ったことがないので不明ですが、factory()に渡す
パラメータはそれだけではないのでは?
そのオブジェクトは『メソッド名が全く一緒なので、利用者は以降の各
メソッドの呼び出しはパラメータに依存しない』事になります。
そういったインターフェースを利用したような形で、利用者が
欲しいクラスオブジェクトを受け取れ、以降の操作を一切変えなくても
良い仕組みになっています。

継承するのはMDB2クラスではありません。
PEARクラスを継承しているMDB2_Driver_Commonクラスになります。
(query()メソッドがあるのはMDB2.php内にあるMDB2_Driver_Commonクラス)
mysqlドライバのクラス(MDB2_Driver_mysqlクラス)を見てみるとMDB2_Driver_Commonを継承しています。
しかし、MDB2_Driver_Common自体を継承する事はできません。
なぜならfactory()で生成されているオブジェクトはMDB2_Driver_Commonクラスではなく
MDB2_Driver_mysqlクラスだからです。
よって、継承するのはMDB2_Driver_mysqlクラスになります。

<?
require("MDB2.php");
require("MDB2/Driver/mysql.php");

class MDB2_Driver_mysqlExt extends MDB2_Driver_mysql {
function &query($query, $types = null, $result_class = true, $result_wrap_class = false)
{
echo "<b>extends class</b><br />";
return parent::query($query, $types, $result_class, $result_wrap_class);
}
}

define('CONFIG_DB_DSN', 'mysqlExt://root:root@localhost/mysql');
$mysqlExt = MDB2::factory(CONFIG_DB_DSN);

$result = $mysqlExt->query("show tables");
while (($row = $result->fetchRow())) {
echo $row[0] . "<br />";
}

$mysqlExt->disconnect();

今回の例ではMySQLになります。
継承するということは別のドライバを作成する事になりますので、
上の例だと、/MDB2/Driver/配下にmysqlExt.phpファイルで以下のような
クラスを定義しておくことで実現できます。
require("MDB2/Driver/mysql.php");

class MDB2_Driver_mysqlExt extends MDB2_Driver_mysql {
function &query($query, $types = null, $result_class = true, $result_wrap_class = false)
{
echo "<b>extends class</b><br />";
return parent::query($query, $types, $result_class, $result_wrap_class);
}
}

継承したドライバ名称は「mysql」ではありませんから、当然
dsnも変わります。
dsnのドライバ名についてはクラス名「MDB2_Driver_mysqlExt」の
「MDB2_Driver_」以降の文字列となります。
ドライバ名にアンダーバー(「_」)があればあるほど、それがディレクトリとなっていきます。
つまり、クラス名が「MDB2_Driver_mysql_Ext」であったとき、
クラスを探しにいくのはMDB2\Driver\mysql\Ext.phpとなり、
dsnのドライバ名も「mysql_Ext」となります。

とまあ、ちょっと調べた結果を載せてみました。
分かった事をだらだらと書き綴ったので理解しづらいかもしれませんが・・・。
    • good
    • 0
この回答へのお礼

コードまでご提示いただきましてありがとうございました。
おかげさまで、無事解決することができました。
FactoryMethodにはじめ今回は自分で勉強不足を痛感しました。

お礼日時:2008/02/02 12:13

書き忘れです・・・。



全部1から作るなら、MDB2_Driver_mysqlクラスのように
MDB2_Driver_Commonを継承してドライバを作ると思います。
私なら面倒なのでしません。「継承したんですよ」ってのが
分かるクラス名にしておけば十分だと思います。
(個人的には。もっとオブジェクト指向に詳しい方からしたら
何と仰るかは不明ですが)
1から作るのはMDB2がサポートしてないDBくらいだと思います。

あと、GoFデザインパターンについての参考URLでも・・・。
http://itpro.nikkeibp.co.jp/article/COLUMN/20051 …
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!