導入

導入 --  DB_DataObject で何ができるか

導入

警告

Zend Optimizerを使用している場合、オプティマイザのバグのため、 最適化レベルを下げ、定数 DB_DATAOBJECT_NO_OVERLOAD = 0 を定義する必要があります。 さもないと、PHP がセグメンテーション違反を起こします。

PHP4でのFIXできないバグのため、 参照渡しの引数を伴うオーバーロードは使用できません (PHP5 ではうまく動作します)。 もし、参照渡しの必要がある場合、定数 DB_DATAOBJECT_NO_OVERLOAD = 0 を定義してください。

DB_DataObject は SQL ビルダおよび PEAR::DB の上位データモデリングレイヤです。 主な目的は、以下の通りです。

これはどういったことでしょうか? より良く書かれた PHP アプリケーションやフレームワークを見ると、 データベースの表などにアクセスする部分をラップするクラスを使用する、 といった共通のアプローチを採っていることに気づくでしょう。 最初の例は次のような person オブジェクトとしてよく見かけられます。
この例は、次のような SQL のテーブルで動作します。
CREATE TABLE IF NOT EXISTS `person` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(64) NOT NULL,
  `password` varchar(32) NOT NULL,
  `birthDate` date NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=13 ;

INSERT INTO `person` (`id`, `name`, `password`, `birthDate`) VALUES
(12, 'John', '098f6bcd4621d373cade4e832627b4f6', '1984-02-23');

このアプローチの主な利点は、単一の表に対する似たようなアクションを グループ化する事ができるということと、重複するコード (例えば、2 つのメソッドが同様のことを行っている) を見つけやすいということでしょう。 また、グローバル変数 $db をここで使用していることに気づくでしょう。 実際にあなたはほとんどの場合で、 全てのクラスで共通のデータベース接続を使用しているでしょう。 では、これをどの様にするべきでしょうか?

次のステップは、値の格納場所としてオブジェクト変数を使用することです。

ご覧の通り、データの現在の行がデータコンテナにストアされ、 オブジェクトのデータを操作するためにメソッドを追加する、 あるいは、他の関連するオブジェクト (例えば、データベース間の表の関連) をコールする事ができます。

次のステップですが、なぜデータベースで検索や取得を実行するためにメンバ変数を利用しないのでしょうか。

ご覧の通り、find メソッドがコールされる前に値がオブジェクトに アサインされることで、クエリに対する条件を設定することができます。 DB_DataObject はこれと同じように動作しますが、 whereAdd() メソッドでさらなる条件を追加する、あるいは、selectAdd() メソッドで選択を制限することもできます。

当然、この方法を進めていき、 データベースの各表に対する小さなコンテナを大量に作成することもでき、 全てのコードはうまく各表と対応するでしょう。しかしながら、 上の例から分かるように、 全てのクラスはメソッドの共通セットのようになります。

このため、これを改善するために DB_DataObject が誕生し、上にある問題に対する統一解として第一歩を踏み出しました。 しかし、多くの問題の複雑さが増すにつれ、 より詳細が調査されていきました。 その結果、DataObjects を持つようになり、 以下の機能を持つほどに成長しました。

では、どの様なクラスになるでしょうか?

例 39-4実際の DataObject コードの最後あたり..

// this is the common configuration code - place in a general site wide include file.

    // this  the code used to load and store DataObjects Configuration.
    $options = &PEAR::getStaticProperty('DB_DataObject','options');

    // the simple examples use parse_ini_file, which is fast and efficient.
    // however you could as easily use wddx, xml or your own configuration array.
    $config = parse_ini_file('example.ini',TRUE);

    // because PEAR::getstaticProperty was called with an & (get by reference)
    // this will actually set the variable inside that method (a quasi static variable)
    $options = $config['DB_DataObject'];




     // this is normally contained in your DataObjects file (autogenerated by the generator)

    require_once 'DB/DataObject.php';


    // by extending the base class DB_DataObject - you inherit all the common methods defined in it.

    class DataObjects_Person extends  DB_DataObject {

        var $id; // this is a primary id (it's specified in a config file - explained later)
        var $name;
        var $friend;

        // this is a simple function to get the persons friends..?

        function getFriends()
        {

            $personObject = $this->factory('person');

            // look for all people with their friend number matching this persons id.
            $personObject->friend = $this->id;

            // do the select query.
            $personObject->find();
            $array = array();

            // fetch the results into the object.
            while ($personObject->fetch()) {
                // use the clone to copy - not really needed but get used to it for PHP5

                $array[] = clone($personObject);
            }
            // return the results.
            return $array;

        }
    }



    // and this goes on your display code

    // create a new person class..
    $person = DB_DataObject::Factory('person');

    // get the person using the primary key.
    $person->get(12);
    // get the friends.
    $friends = $person->getFriends();

    //  DB_DataObjects is designed to make print_r useable to debug your applications.
    print_r($friends);

上の例は DB_DataObject のコンポーネントを表しています。オプションを設定することで、 全てのコアオブジェクトは、生成された ini ファイルからデータ定義を自動的に読み込み、 データベースにどの様にアクセスすればよいか知ることができます (複数のデータベースもサポートしています - 設定の節を参照してください)。

上のクラス定義には、あなたは全ての共通のメソッドを無視し、 データ特有のコードを定義する必要があるだけである、 という事を示しています。また、 複数行のデータを処理するメソッドも併せて 1 つ示されています。

後半は、どの様にクエリを発行して単一行の結果を取得するか が示されています。 $person->get() はデータベースに接続し、クエリを実行し、結果をフェッチし、 クエリから返されたデータをオブジェクト変数に割り当てます。

大まかには、メソッド名は関連する SQL ステートメントと同じです。