3

我有一个从中扩展的基本模型。在其中,我定义了两个验证过滤器。一个检查记录是否唯一,另一个检查记录是否存在。它们的工作方式完全相同,只是返回值与另一个相反。

因此,两次编写相同的代码只返回不同的值听起来是不对的。我想知道如何从另一个调用一个自定义验证器。

这是我的unique验证器代码:

<?php
Validator::add('unique', function($value, $rule, $options) {
    $model = $options['model'];
    $primary = $model::meta('key');

    foreach ($options['conditions'] as $field => $check) {
        if (!is_numeric($field)) {
            if (is_array($check)) {
                /**
                 * array(
                 *   'exists',
                 *   'message'    => 'You are too old.',
                 *   'conditions' => array(
                 *       
                 *       'Users.age' => array('>' => '18')
                 *   )
                 * )
                 */
                $conditions[$field] = $check;
            }
        } else {
            /**
             * Regular lithium conditions array:
             * array(
             *   'exists',
             *   'message'    => 'This email already exists.',
             *   'conditions' => array(
             *       'Users.email' //no key ($field) defined
             *   )
             * )
             */
            $conditions[$check] = $value;
        }
    }

    /**
     * Checking to see if the entity exists.
     * If it exists, record exists.
     * If record exists, we make sure the record is not checked
     * against itself by matching with the primary key.
     */
    if (isset($options['values'][$primary])) {
        //primary key value exists so it's probably an update
        $conditions[$primary] = array('!=' => $options['values'][$primary]);
    }

    $exists = $model::count($conditions);
    return ($exists) ? false : true;
});
?>

exists应该像这样工作:

<?php
Validator::add('exists', function($value, $rule, $options) {
    $model = $options['model'];
    return !$model::unique($value, $rule, $options);
});
?>

但显然,不能那样做。我是否必须将验证函数定义为匿名函数,将其分配给变量并将其传递而不是闭包?或者有什么方法可以unique从内部调用exists

4

2 回答 2

2

匿名函数方法可以工作。然后您可以在为“存在”验证器定义的另一个匿名函数中使用该变量。这是另一个将其合并到您的基本模型类中的想法:

<?php

namespace app\data\Model;

use lithium\util\Validator;

class Model extends \lithium\data\Model {

    public static function __init() {
        static::_isBase(__CLASS__, true);
        Validator::add('unique', function($value, $rule, $options) {
            $model = $options['model'];
            return $model::unique(compact('value') + $options);
        });
        Validator::add('exists', function($value, $rule, $options) {
            $model = $options['model'];
            return !$model::unique(compact('value') + $options);
        });
        parent::__init();
    }

    // ... code ...

    public static function unique($options) {
        $primary = static::meta('key');

        foreach ($options['conditions'] as $field => $check) {
            if (!is_numeric($field)) {
                if (is_array($check)) {
                    /**
                     * array(
                     *   'exists',
                     *   'message'  => 'You are too old.',
                     *   'conditions' => array(
                     *
                     *     'Users.age' => array('>' => '18')
                     *   )
                     * )
                     */
                    $conditions[$field] = $check;
                }
            } else {
                /**
                 * Regular lithium conditions array:
                 * array(
                 *   'exists',
                 *   'message'  => 'This email already exists.',
                 *   'conditions' => array(
                 *     'Users.email' //no key ($field) defined
                 *   )
                 * )
                 */
                $conditions[$check] = $options['value'];
            }
        }

        /**
         * Checking to see if the entity exists.
         * If it exists, record exists.
         * If record exists, we make sure the record is not checked
         * against itself by matching with the primary key.
         */
        if (isset($options['values'][$primary])) {
            //primary key value exists so it's probably an update
            $conditions[$primary] = array('!=' => $options['values'][$primary]);
        }

        $exists = $model::count($conditions);
        return ($exists) ? false : true;
    }

}

?>
于 2012-04-10T20:52:57.603 回答
1

我最终创建了一个包含我需要的功能的单独方法,然后从我的验证过滤器中调用它。我已经精简了我的基本模型,只保留其中的相关数据。希望它可以帮助有类似问题的人。

<?php
namespace app\extensions\data;
class Model extends \lithium\data\Model {

    public static function __init() {
        parent::__init();

        Validator::add('unique', function($value, $rule, $options) {
            $model  = $options['model'];
            return ($model::exists($value, $rule, $options, $model)) ? false : true;
        });

        Validator::add('exists', function($value, $rule, $options) {
            $model  = $options['model'];
            return ($model::exists($value, $rule, $options, $model)) ? true : false;
        });
    }


    public static function exists($value, $rule, $options, $model) {
        $field   = $options['field'];
        $primary = $model::meta('key');

        if (isset($options['conditions']) && !empty($options['conditions'])) {
            //go here only of `conditions` are given
            foreach ($options['conditions'] as $field => $check) {
                if (!is_numeric($field)) {
                    if (is_array($check)) {
                        /**
                         *   'conditions' => array(
                         *       'Users.age' => array('>' => 18) //condition with custom operator
                         *   )
                         */
                        $conditions[$field] = $check;
                    }
                } else {
                    /**
                     * Regular lithium conditions array:
                     *   'conditions' => array(
                     *       'Users.email' //no key ($field) defined
                     *   )
                     */
                    $conditions[$check] = $value;
                }
            }
        } else {
            //since `conditions` is not set, we assume
            $modelName = $model::meta('name');
            $conditions["$modelName.$field"] = $value;
        }

        /**
         * Checking to see if the entity exists.
         * If it exists, record exists.
         * If record exists, we make sure the record is not checked
         * against itself by matching with the primary key.
         */
        if (isset($options['values'][$primary])) {
            //primary key value exists so it's probably an update
            $conditions[$primary] = array('!=' => $options['values'][$primary]);
        }

        return $model::count($conditions);
    }
}
?>
于 2012-04-10T11:16:13.787 回答