May 26, 2013

FuelPHPのバリデーションで自身を除いた一意性チェックのより冴えた(?)方法

先に、以下をご覧ください。

FuelPHPのバリデーションで自身を除いた一意性チェック
http://madroom-project.blogspot.jp/2013/05/fuelphp.html

今回は、上記の記事の内容を、より汎用的に使う方法です。

Configファイル(仮に config/app.php とします)に、以下を記述します。
<?php

return array(
    'functions' => array(
        '_validation_not_taken' => function($val, $model_name, $id, $column) {
            if (empty($id))
            {
                $exclude_val = null;

            }
            else
            {
                $exclude = $model_name::find($id);

                $exclude_val = ! empty($exclude->$column) ?
                    $exclude->$column : null;
            }

            if ($exclude_val !== null and $exclude_val === $val)
            {
                return true;
            }

            $method_name = 'find_by_'.$column;
            $model = $model_name::$method_name($val);
            return empty($model);
        }
    ),
);
以下のように使います。
$v = Validation::forge();
$v->add('uname', 'uname')
    ->add_rule(array('already_taken' => Arr::get(Config::get('app.functions'), '_validation_not_taken')),
        'Model_Xxx', $self_id, 'uname');
add_ruleに渡すパラメータは、対象のモデル名、除外したいレコードのID値、対象となるカラム名。です。

対象となるカラム名を配列で渡せるように拡張すれば、複合チェックも出来そうです。(今回はそこまではやっていませんが。)

Config::get('app.functions._validation_not_taken')のようにクロージャを直接Config::getすると、どうも
https://github.com/fuel/core/blob/888f6d914f3edca33d3ad4fab002b5ddce4bf5b1/classes/fuel.php#L341
で即コールされてしまうようで、Config::getでクロージャ一覧の配列をgetして、更にArr::getしています。

ホントは独自クラスに実装した方が良いのかもしれませんが、Configだと手元にあるファイルだけで出来て楽だなとも思いました。

No comments:

Post a Comment