ありがとう。また会おう。

ゆるいかんじで。かたのちからぬいて。やってます。

MDB2のMDB2_FETCHMODE_OBJECTがgdgdな件。

まあ今時は、「漢ならPDO」なのかもしれんのですが、業務では諸々の事情で使えなかったりするわけで、MDB2を使ってたりするんですが。


で、PEARマニュアルとAPIリファレンス見てて、こういうことできるのかと思ったんだが。
http://pear.php.net/manual/ja/package.database.mdb2.intro-fetch.php
http://pear.php.net/package/MDB2/docs/latest/MDB2/MDB2_Driver_Common.html#methodsetFetchMode

<?php
//もちろん実際には正しいDSN接続文字列が入ってる。
define(DB_DSN, 'pgsql://pgsql://someuser:password@localhost/somedb');

$mdb2 = MDB2::factory(DB_DSN);

//Hoge は取得したデータを格納したいDAO
$mdb2->setFetchMode(MDB2_FETCHMODE_OBJECT, 'Hoge');

$sql = 'select * from hoge where id = 1';
$res = $mdb2->query($sql);
//ここで、$hogeはHogeクラスのインスタンスが入る
$hoge = $res->fetchRow();

var_dump($hoge);

としたら、空の(プロパティが何もセットされてない)$hogeオブジェクトが返ってきたよ!(〇o〇;))))!!


で、setFetchModeの第2引数を削除すると、

<?php
    $mdb2->setFetchMode(MDB2_FETCHMODE_OBJECT);

stdClassのプロパティに値がセットされたものが返ってきた!( ̄□ ̄;)


意味がわからんので、ソースをよんでみた。
/path/to/pear/MDB2/Driver/pgsql.php の 1065行目あたりから。

    function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null)
    {
   //中略
        if ($fetchmode == MDB2_FETCHMODE_DEFAULT) {
            $fetchmode = $this->db->fetchmode;
        }
        if ($fetchmode & MDB2_FETCHMODE_ASSOC) {
            $row = @pg_fetch_array($this->result, null, PGSQL_ASSOC);
            if (is_array($row)
                && $this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE
            ) {
                $row = array_change_key_case($row, $this->db->options['field_case']);
            }
        } else {
            $row = @pg_fetch_row($this->result);
        }
   //中略
        if ($fetchmode === MDB2_FETCHMODE_OBJECT) {
            $object_class = $this->db->options['fetch_class'];
            if ($object_class == 'stdClass') {
                $row = (object) $row;
            } else {
                $row = &new $object_class($row);
            }
        }
        ++$this->rownum;
        return $row;
    }

・・・え?Σ(・□・ )

<?php
$row = &new $object_class($row);

ってことは・・・newしてコンストラクタ呼び出してるだけじゃん!!w(☆o◎)w
てことは、プロパティのセットはてめえでやれと!!(-.-”)凸


しかも、データを取得するところは、MDB2_FETCHMODE_OBJECTだと

<?php
    $row = @pg_fetch_row($this->result);

を通るから、コンストラクタに渡ってくるデータって連想配列じゃなくて、数値連番配列。。。
これじゃカラムの並び順を考慮しなきゃいかんじゃん。。。
それって使えなさすぎ。。。orz


ちなみに第2引数を設定しなかった場合は

<?php
$row = (object) $row;

を通るから、ちゃんとキャストされてプロパティに値がセットされるんだね。。。納得。


ちなみにちなみに、MySQLも同じ実装なのでやっぱだめ。
数値配列をコンストラクタに渡すところまで律儀に一緒。。。orz


てことで、MDB2の機能だけでORマッパーもどきは残念ながら無理そうだね。。。


PDOならできそうだけど。試してない。