とりあえず

先日のsymfony勉強会の懇親会で、Doctrineはオブジェクトのプロパティを取得する方法がたくさんあるけどどうなの?みたいな話があったのでちょっとまとめておきます。

<?php
$article = Doctrine::getTable('Article')->find(1);

$article->getTitle();
$article->get('title');
$article->title;
$article['title'];

Doctrineは上記の4つの方法でオブジェクトのプロパティを取得できます。ちなみに上記はtitleフィールドを取得する場合の例です。

最初に言っておくと、一番上のgetTitle()はDoctrineの機能としては実は提供されていません。これはsfDoctrineRecordの実装で、多分symfonyで使うためPropelにあわせたのではないかと思われます。

んで下の3つはDoctrineが提供している機能です。get()はメソッドアクセスだとすぐわかりますが下の2つは直接プロパティにアクセスしてるみたいで気持ち悪い!とお話がありました。

ですがこれは実は直接アクセスしてるわけではありません。そもそもDoctrineはプロパティを直接変数として持っておらず、全て1つの配列として持っています。

じゃあ何なの?ということなのですが。Doctrine_Recordの親の親クラスがDoctrine_Accessというクラスですが、こいつが色々やってます。

http://trac.doctrine-project.org/browser/branches/1.0/lib/Doctrine/Access.php

まずDoctrine_AccessクラスはSPLのArrayAccessインターフェイスを実装しています。んで内部ですが、offsetGetメソッドと__getメソッドが共に内部で$this->get(フィールド名)を呼び出すようになっています。

というわけで、この3つのアクセス方法は全てgetメソッドにアクセスしにいく、ということになっています。

ここまでわかれば後はgetTitle()とget('title')の違いです。先ほどgetTitle()はsfDoctrineRecordの実装と書きましたが、実はget()もオーバーライドされています。


・・・・・とここまで書いてtrunkのsfDoctrineRecordをみたらかなり実装が変わっていたというオチ。get()メソッドがなくなってる。。。

1.1までで一応言っておくと、getTitle()が実際に実装されていればそれを必ず見に行くようにget()がオーバーライドされています。実装されていない場合にgetTitle()を使った場合はというと、__callメソッドからparent::get()が呼び出されるようになっています。

というまあグダグダな感じになってしまいました。まさかこんな風に実装が変わっているとは・・・。しかもcreated_atとupdated_atが何も設定せずに更新されるようになってるっぽい。trunk変わりすぎ。

とりあえずDoctrineRecord自体の実装は大丈夫です。変わってないです。sfDoctrineRecordがかなり変わってます。ですので、自前でgetTitle()を実装している場合にget('title')とかとやったときの挙動が今までと変わっているかもしれない、ということです。

これについてはまた後日じっくり調べさせていただきます。