Help us understand the problem. What is going on with this article?

FuelPHPのValidationにクロージャを使う

More than 5 years have passed since last update.

例としてログインするときのvalidateは大きくわけると以下のとおり。

  • ID(email等)の必須チェック
  • パスワードの必須チェック
  • IDとパスワードでログインできるか

最初の2つはドキュメント通りでいいですが、最後のvalidateは、2つの項目が必要になります。
FuelPHPの基本的なvalidateは、いずれかの項目に対して行うので、ログインチェックのような複数の項目を取り扱うにはちょっと扱いづらいです。
そこで無名関数(Closure)の出番となります。

user.php
<?php
    public static function login_validate()
    {
        $val = Validation::forge();
        $val->add_field('email', 'Email','required');
        $val->add_field('password', 'パスワード', 'required');

        $email = Input::post('email');
        $password = Input::post('password');
        $val->add('dummy', 'dummy')->add_rule(
            function () use ($email, $password) { // login_validate
                if (!$email || !$password) {
                    return true;
                }
                $user = Model_User::query()->
                    where('email', $email)->
                    where('password', $password)->
                    where('del_flg', 0)->get_one();

                if ($user) {
                    return true;
                } else {
                    Validation::active()->set_message('closure', 'ログインに失敗しました。');
                    return false;
                }
            }
        );
        return $val;
    }

「ログイン失敗」のvalidate対象は2項目あるので、対象のフィールドは"dummy"にしています。(使いません)
add_ruleには無名関数が渡せますので、use句で引数を与えましょう。(レキシカル変数)
functionに引数がないのは、addで追加したフィールドを使用しないためです。

emailのフィールドにログイン可否のvalidateを仕込むと以下のようになります。

user.php
<?php
    public static function login_validate()
    {
        $val = Validation::forge();

        $password = Input::post('password');
        $val->add('email', 'Email')
            ->add_rule('required')
            ->add_rule( // login_validate
                function($email) use ($password) {
                    if (!$email || !$password) {
                        return true;
                    }
                    $user = Model_User::query()->
                        where('email', $email)->
                        where('password', $password)->
                        where('del_flg', 0)->get_one();

                    if ($user) {
                        Session::set('login_user', $user);
                        $user->store();
                        return true;
                    } else {
                        Validation::active()->set_message('closure', 'ログインに失敗しました。');
                        return false;
                    }
                });
        $val->add_field('password', 'パスワード', 'required');
        return $val;
    }

無名関数の引数はaddで指定したemail値が渡され、パスワードはレキシカル変数としてclousureに持ちます。
作成したクロージャに再利用性があるなら適当なクラスにクロージャを返すユーザ定義関数作るといいと思います。

という感じにFuelPHPのValidationにクロージャを使うとValidation無双できるよというお話でした。

追記

FuelPHP Advent Calendar 2013にて、バリデーションにClosureを利用する際の注意点を記載しました。
FuelPHPを更に使ってみて使えるなと思った拡張ValidationRuleの書き方とCore拡張の小技

ya-sasaki
道端で踊れるDeveloper。 アプリケーションアーキテクト、ソフトウェアアーキテクト(と名乗ってみたい)。社内のサーバ屋さん。
http://qiita.com/ya-sasaki
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away