Lithium: how to invoke one check filter from within another

I have a basic model that I am expanding from. In it, I defined two validation filters. One checks if the record is unique, the other checks if the record exists. They work exactly the same, except that the return value will be the opposite of the other.

Thus, it is wrong to write the same code twice to return a different value. I would like to know how can I call one custom validator from another.

Here's my code for the validator 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 probably an update
        $conditions[$primary] = array('!=' => $options['values'][$primary]);
    }

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

      

exists

should work like this:

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

      

But obviously this cannot be done. Should I define the validation function as an anonymous function, assign it to a variable and pass it instead of the closure? Or is there a way I can call unique

from exists

?

+3


source to share


2 answers


The anonymous function method will work. And then you can use that variable in another anonymous function that you define for the "exists" validator. Here's another idea that includes it in your base model class:



<?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 probably an update
            $conditions[$primary] = array('!=' => $options['values'][$primary]);
        }

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

}

?>

      

+2


source


I ended up creating a separate method that contains the functions I needed and then called it from my validation filter. I have cropped the base model so that only relevant data is stored in it. Hope this helps someone with a similar problem.



<?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 probably an update
            $conditions[$primary] = array('!=' => $options['values'][$primary]);
        }

        return $model::count($conditions);
    }
}
?>

      

+1


source







All Articles