こちらも併せて御覧ください。
http://madroom-project.blogspot.com/2011/12/ormmodelobservers.html
まず、以下2つのテーブルがあることとします。
usersが親。twitter_usersが子。
users.id = twitter_users.user_idの関係です。
create table users ( id int not null auto_increment, created_at int not null, updated_at int not null, primary key (id) ); create table twitter_users ( id int not null auto_increment, created_at int not null, updated_at int not null, user_id int not null unique, twitter_user_id varchar(255) not null unique, twitter_screen_name varchar(255) not null, twitter_oauth_token varchar(255) not null, twitter_oauth_token_secret varchar(255) not null, primary key (id) );一見、1:1なので、usersにまとめられそうですが、その辺りは大人の事情です。
これをOrm\Modelで表現するにはどうするか。が今回の話です。
まず、親となるusersテーブルに対するモデル。
app\classes\model\user.php
namespace Model; class User extends \Orm\Model { protected static $_observers = array( 'Orm\Observer_CreatedAt' => array('before_insert'), 'Orm\Observer_UpdatedAt' => array('before_save'), ); protected static $_has_one = array( 'twitter_user' => array( 'key_from' => 'id', 'model_to' => 'Model\Twitter_User', 'key_to' => 'user_id', 'cascade_save' => true, // true/falseどちらで有るべきか、要調査。とりあえずはドキュメント通り。 'cascade_delete' => true, // falseにすると、削除時にtwitter_userが削除されなかった。 ) ); }
次に、子となるtwitter_usersテーブルに対するモデル。
\app\classes\model\twitter\user.php
namespace Model; class Twitter_User extends \Orm\Model { protected static $_observers = array( 'Orm\Observer_CreatedAt' => array('before_insert'), 'Orm\Observer_UpdatedAt' => array('before_save'), ); protected static $_belongs_to = array( 'user' => array( 'key_from' => 'user_id', 'model_to' => 'Model\User', 'key_to' => 'id', 'cascade_save' => false, // trueにすると一切の変更がない場合のsave()でエラーとなる。 'cascade_delete' => false, // trueにすると削除時に親も消してしまう。注意。 ) ); }
* 親のモデルは、子のモデルを$_has_oneで定義する。
* 子のモデルは、親のモデルを$_belongs_toで定義する。
みたいなニュアンスでしょうか。(果たして認識は正しいだろうか。。。)
とりあえずドキュメントのままです。(今度調べよう。名前からなんとなく憶測はできるけど。。。)
これで、例えば検索は
$user = User::find_by_id(1);
すると
$screen_name = $user->twitter_user->twitter_screen_name;
とか出来ます。
$user->twitter_userは、存在しない場合、nullになるようです。
saveする場合も、例えば
$twitter_user = new Twitter_User;
$twitter_user->user = new User;
して、
$twitter_user->twitter_user_id = [Twitterのuser_id];
や、その他のカラム値をセットして
$twitter_user->save();
すると、親を含めて一発登録出来ました。
追記:(上記ソースには以下の対処を反映済。)
上記の方法でsaveした時、一切の変更がない場合に、以下のエラーが発生しました。
Orm\FrozenObject [ Error ]: No changes allowed.
子のモデル(\app\classes\model\twitter\user.php)の$_belongs_toの
'cascade_save'をfalseに変更したところ、発生はしなくなりましたが、
一切の変更がない場合でも、updateが走るようになりました。
(updated_atのみが更新されます。)
とりあえず問題は無いですが、この辺りはしっかりと把握しておきたいなぁ。
参考:
http://docs.fuelphp.com/packages/orm/relations/belongs_to.html
http://docs.fuelphp.com/packages/orm/relations/has_one.html
P.S.
それぞれのモデルで$_observersというのがありますが、
これは、今回の話にはあまり関係有りません。。。
No comments:
Post a Comment