Doctrineメモ

ぼちぼちDoctrineを使い始めようということで趣味プロジェクトをsymfony1.3+Doctrineで作り始めました。
Doctrineについての知識が全くないので、Propelとの違いなど(初歩的なことから)個人的にメモしていきます。

注)symfony1.3ではDoctrineがORMのデフォルトです。

schema.yml

  • Doctrineの場合のschema.ymlの書き方のリファレンスは以下
  • カラムの型を単純に「integer」と書くとBIGINTになる。
    • 小さいサイズにしたい場合は、「integer(4)」などと書く
    • 同様に、暗黙に生成されるidカラム(プライマリキー)はそのままだとBIGINTになる。
      • 明示的にidカラムをinteger(4)などで指定すれば変更できる
      • 明示的にidカラムを指定する場合は、主キーやオートインクリメントの設定も忘れずに
HogeTable:
  actAs:                     { Timestampable: ~ }
  columns:
    id:
      type:                  integer(4)
      primary:               true
      autoincrement:         true
  • カラムの型に「tinyint」などと書くことができるが、この場合なぜかdefaultの設定が上手く抽出されない。
    • tinyintを使いたければ「integer(1)」と書く

レコードの保存

Doctrinでも、Propelと同様にフィールドに対応するアクセサメソッドを利用することができます。

<?php
$login = new LoginTable();
$login->setLoginName('Foo Bar');
$login->save();

ただし、Propelの場合はレコードオブジェクトのアクセサメソッドや、Peerクラスのフィールド名定数などがあらかじめ定義されていたのに対し、Doctrineの場合はベースクラスのマジックメソッドによってアクセサメソッドを実現しています。
コードの見た目ではさほど変わらないのですが、私の場合はEclipse+PDT環境でコードアシストを使いまくってコーディングしていたので、Doctrineのこのような仕組みの場合はコード補完してくれなくてちょっと困っています。
→※アクセサメソッドの生成


あと、上記以外に以下のような方法もあるようです。

<?php
//  汎用のsetメソッドを利用する
$login->set('login_name', 'Foo Bar');

//  メンバ変数に直接代入する
$login->login_name = 'Foo Bar';


参考:


この「実行時アクセサ(getter/setter)」の正体は、sfDoctrineRecordクラスの__callマジックメソッドです。

Doctrineでモデルクラスに静的にアクセサメソッドを生成する

上で書いたようにEclipse+PDT環境で補完を使いたいために、いろいろ調べてみたところ、どうやら「昔はアクセサの生成機能があった」ようですが、設計理念などの理由でアクセサの生成機能は削除されたようです。(が、コードの一部が残っています)

なお、アクセサの生成は以下で行われています。
Import/Builder.php buildAccessors

※ただし、下に述べますがこのコードをそのまま使うと無限ループに(苦笑)

※もともとは、schema.ymlに「generate_accessors: true」と書くとアクセサが生成される、という仕様だったぽいですね。


とりあえずアクセサが生成されればよいので、以下のような修正をしてみました。

  • Import/Builder.php
    • そのままだとダメなので、まずはbuildAccessorsの生成コード部分を修正
      • get→_get、set→_setに。
    • loadTemplateメソッドでアクセサ用のテンプレートを追加
<?php
    self::$_tpl = '/**'
                . '%s' . PHP_EOL
                . ' */' . PHP_EOL
                . '%sclass %s extends %s' . PHP_EOL
                . '{'
                . '%s' . PHP_EOL
                . '%s' . PHP_EOL
                . '%s' . PHP_EOL
                . '}';
    • buildDefinitionメソッドでアクセサの生成メソッドを呼び出し、テンプレートへの適用
<?php
    $accessorsCode = $this->buildAccessors($definition);

    $content = sprintf(self::$_tpl, $docs, $abstract,
                                   $className,
                                   $extends,
                                   $tableDefinitionCode,
                                   $setUpCode,
                                   $accessorsCode);

このようにした後、symfony doctrine:buil-allなどを実行すると、無事アクセサが生成されました。

※パフォーマンスはアクセサの有り/無しでほとんど変わらないようです。



参考:

日付カラムのgetter/setter

getDateTimeObject、setDateTimeObject()メソッド

※ツッコミ、上手いやり方のご指摘など大歓迎です!