「最速」PHPフレームワークPhalconのモデルについて、基本事項をまとめます(公式ドキュメントの翻訳+αです)。記事執筆時のPhalconのバージョンは1.3.1です。

ビヘイビア

ビヘイビアとは、複数のモデルに共有される振る舞いのことです。PhalconのORマッパーは、モデルでビヘイビアを実装するためのAPIを提供しています。また、イベントとコールバックを使用して、より自由度の高いビヘイビアを実装することもできます。

ビヘイビアは、モデルの初期化処理に加えなければなりません。モデルは複数のビヘイビアをもつことができます。

<?php

use Phalcon\Mvc\Model\Behavior\Timestampable;

class Users extends \Phalcon\Mvc\Model
{
    public $id;

    public $name;

    public $created_at;

    public function initialize()
    {
        $this->addBehavior(new Timestampable(
            array(
                'beforeCreate' => array(
                    'field' => 'created_at',
                    'format' => 'Y-m-d'
                )
            )
        ));
    }

}

フレームワークは、以下の組み込みビヘイビアを提供しています。

名前 説明
Timestampable レコードが作成・更新される際に、自動的にモデルのフィールドを更新する
SoftDelete 永続的な削除(物理削除)の代わりに、削除フラグを付与する(論理削除)

Timestampable

このビヘイビアは、配列をオプションとして受け取ります。最初のキーが、カラムへの代入が行われるイベント名になります。

<?php

public function initialize()
{
    $this->addBehavior(new Timestampable(
        array(
            'beforeCreate' => array(
                'field' => 'created_at',
                'format' => 'Y-m-d'
            )
        )
    ));
}

それぞれのイベントには独自のオプションがあり、fieldは更新されるカラム名になります。formatが文字列なら、PHPのdate()関数の引数として渡されます。formatには無名関数を使うこともでき、お好みの形式でタイムスタンプを作ることができます。

<?php

public function initialize()
{
    $this->addBehavior(new Timestampable(
        array(
            'beforeCreate' => array(
                'field' => 'created_at',
                'format' => function() {
                    $datetime = new Datetime(new DateTimeZone('Europe/Stockholm'));
                    return $datetime->format('Y-m-d H:i:sP');
                }
            )
        )
    ));
}

formatがオプションの配列に含まれない場合は、タイムスタンプはPHPのtime()関数を使用し、タイムスタンプの数値が代入されます。

SoftDelete

このビヘイビアは、以下のように使います。

<?php

use Phalcon\Mvc\Model\Behavior\SoftDelete;

class Users extends \Phalcon\Mvc\Model
{

    const DELETED = 'D';

    const NOT_DELETED = 'N';

    public $id;

    public $name;

    public $status;

    public function initialize()
    {
        $this->addBehavior(new SoftDelete(
            array(
                'field' => 'status',
                'value' => Users::DELETED
            )
        ));
    }

}

このビヘイビアは、2つのオプションを受け取ります。fieldは更新されるフィールド名を、valueは削除フラグの値を指定します。以下のようなデータをもつusersテーブルについて考えてみます。

mysql> select * from users;
+----+---------+--------+
| id | name    | status |
+----+---------+--------+
|  1 | Lana    | N      |
|  2 | Brandon | N      |
+----+---------+--------+
2 rows in set (0.00 sec)

もし、いずれかのレコードを削除したら、レコードが削除される代わりに、statusが更新されます。

<?php

Users::findFirst(2)->delete();

上記コードが実行されると、テーブルの中のデータは以下のようになります。

mysql> select * from users;
+----+---------+--------+
| id | name    | status |
+----+---------+--------+
|  1 | Lana    | N      |
|  2 | Brandon | D      |
+----+---------+--------+
2 rows in set (0.01 sec)

削除済みか否かのフラグをクエリで明示的に指定してやる必要がある点に注意してください。テーブルが上の状態の時、以下のコードを実行すると、削除されたはずのBrandonも取得されてしまいます。

$users = Users::find();

論理削除済みのレコードを除外するには、以下のようにします。

$users = Users::find('deleted = ' . Users::NOT_DELETED);

独自のビヘイビアを作る

ORマッパーは、独自のビヘイビアのためのAPIを提供しています。ビヘイビアは、Phalcon\Mvc\Model\BehaviorInterfaceを実装したクラスでなければなりません。また、Phacon\Mvc\Model\Behaviorが、ビヘイビアの実装に必要なほとんどのメソッドを提供しています。

以下のビヘイビアは、1つの実装例です。Blamableビヘイビアは、ユーザーがモデルに行った操作を特定します。

<?php

use Phalcon\Mvc\Model\Behavior;
use Phalcon\Mvc\Model\BehaviorInterface;

class Blameable extends Behavior implements BehaviorInterface
{

    public function notify($eventType, $model)
    {
        switch ($eventType) {

            case 'afterCreate':
            case 'afterDelete':
            case 'afterUpdate':

                // セッションからユーザー名取得
                $userName = $this->getDI()->get('session')->get('userName');

                // ユーザー名・イベント種別・主キーをログに記録
                file_put_contents(
                    'logs/blamable-log.txt',
                    $userName . ' ' . $eventType . ' ' . $model->id
                );

                break;

            default:
                /* 他のイベントは無視する */
        }
    }

}

次に、このビヘイビアをモデルに追加してみます。

<?php

class Profiles extends \Phalcon\Mvc\Model
{

    public function initialize()
    {
        $this->addBehavior(new Blamable());
    }

}

ビヘイビアは、不明なメソッド呼び出しに対して割り込みができます。

<?php

use Phalcon\Mvc\Model\Behavior,
    Phalcon\Mvc\Model\BehaviorInterface;

class Sluggable extends Behavior implements BehaviorInterface
{

    public function missingMethod($model, $method, $arguments=array())
    {
        // 「getSlug」メソッドが呼ばれたら、titleを変換する
        if ($method == 'getSlug') {
            return Phalcon\Tag::friendlyTitle($model->title);
        }
    }

}

Sluggableを実装しているモデルにgetSlug()メソッドの呼び出しを行うと、SEO対策のされたtitleが返ります。

<?php

$title = $post->getSlug();

トレイトをビヘイビアとして使う

PHP5.4以降では、トレイトを使うことでクラスのコードの再利用ができます。この機能を使って、独自のビヘイビアを実装することもできます。以下のトレイトは、TimeStampableビヘイビアのシンプルな実装例です。

<?php

trait MyTimestampable
{

    public function beforeCreate()
    {
        $this->created_at = date('r');
    }

    public function beforeUpdate()
    {
        $this->updated_at = date('r');
    }

}

モデルでは、以下のようにして利用します。

<?php

class Products extends \Phalcon\Mvc\Model
{
    use MyTimestampable;
}

今回はここまで

今回は、Phalconのモデルで利用可能なビヘイビアについて紹介しました。次回は、Transactionsから先をみていきます。