FuelPHPのORM Observerはとても便利

  • 64
    Like
  • 0
    Comment
More than 1 year has 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とかも使えるので、こういうケースだと使い勝手がすごくいい。
細かい部分でスキーマレスなデータを取り扱いたくなるとき、ラララ〜って感じで小さく書ける。