Edited at

FuelPHPのORM Observerはとても便利

More than 5 years have passed since last update.


ORM Observer

FuelPHPのORMパッケージに含まれるオブザーバがとても便利。

イベントベースになっていて、特定のイベント発生時に処理を行うことが出来る。

たとえば、before_insert, before_save, after_loadなどのタイミング。

標準でいくつかのオブザーバが付属していて、自前で作ることもできる。


付属オブザーバ


  • Observer_Self


    • 任意のイベント発生時に、モデルに含まれる任意の関数を実行する



  • Observer_CreatedAt


    • レコードが挿入されたときにcreated_atを設定



  • Observer_UpdatedAt


    • レコードが更新されたときにupdated_atを設定



  • Observer_Validation


    • レコードの挿入・更新前にカラムのデータをバリデーションする



  • Observer_Typing


    • カラムのデータをキャストする



  • Observer_Slug


    • URLのスラグを生成する




試してみる


テストデータ

とりあえず説明用にMySQLに適当なテーブルを追加してテストデータを投入。

CREATE TABLE `students` (

`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '',
`blood_type` varchar(10) DEFAULT '',
`favorite_things` text NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime DEFAULT NULL,
`deleted_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

ScreenShot 2014-05-28 20.04.54.png


Model_Studentを作成

このような感じで、カラム名や論理削除フラグ、主要な4つのオブザーバを設定。


student.php

class Model_Student extends Orm\Model_Soft

{
protected static $_primary_key = array('id');

protected static $_soft_delete = array(
'mysql_timestamp' => true,
);

protected static $_properties = array(
'id',
'blood_type' => array(
'data_type' => 'var_char',
'validation' => array(
'match_pattern' => array('@\A(A|B|O|AB)\z@'),
),
),
'name' => array(
'data_type' => 'varchar',
),
'favorite_things' => array(
'data_type' => 'json',
),
'created_at' => array(
'data_type' => 'time_mysql',
),
'updated_at' => array(
'data_type' => 'time_mysql',
),
'deleted_at' => array(
'data_type' => 'time_mysql',
)
);

protected static $_observers = array(
'Orm\Observer_Typing' => array(
'events' => array('before_save', 'after_save', 'after_load')
),
'Orm\Observer_Validation' => array(
'events' => array('before_insert', 'before_save'),
),
'Orm\Observer_UpdatedAt' => array(
'events' => array('before_save'),
'mysql_timestamp' => true,
),
'Orm\Observer_CreatedAt' => array(
'events' => array('before_insert'),
'mysql_timestamp' => true,
),
);
}



TypingでJSONもデコード

モデルをfindして取得するだけで、以下のようにキャストされる。

$student = \Model_Student::find(1);

/*
array (
'blood_type' => 'O',
'name' => 'Ichigo Hoshimiya',
'favorite_things' =>
stdClass::__set_state(array(
'color' => 'pink',
'genre' => 'cute',
'brand' => 'Angely Sugar',
)),
'created_at' =>
Fuel\Core\Date::__set_state(array(
'timestamp' => 1349659654,
'timezone' => 'Asia/Tokyo',
)),
'updated_at' =>
Fuel\Core\Date::__set_state(array(
'timestamp' => 1401273534,
'timezone' => 'Asia/Tokyo',
)),
'deleted_at' => NULL,
'id' => '1',
)
*/

ここにはないけど、int型やfloat型も、もちろんキャストされる。

tinyint(1)のカラムに、data_typeでboolを設定しておくとtrue/falseになったり。とっても便利。


Validationでバリデーション

$student = \Model_Student::find(1);

try
{
$student->blood_type = 'AC';
$student->save();
}
catch (\Orm\ValidationFailed $e)
{
echo $e->getMessage();
// The field blood_type must match the pattern @\A(A|B|O|AB)\z@.
}

blood_typeに「AC」を入れてsaveしようとしても、match_patternで「A, B, O, AB」のどれかに制限されているのでエラーになる。


CreatedAt, UpdatedAt

もちろんupdateしてsaveすれば、updated_atが更新される。

$student = \Model_Student::find(1);

$student->favorite_things->lucky_charm = 'おしゃもじ';
$student->save();

ScreenShot 2014-05-28 20.15.35.png


Typingマジ便利

JSONの他にもserializeとかも使えるので、こういうケースだと使い勝手がすごくいい。

細かい部分でスキーマレスなデータを取り扱いたくなるとき、ラララ〜って感じで小さく書ける。