I have a base model that I extend from. In it, I have defined two validation filters. One checks if a record is unique, the other checks if a record exists. They work the exact same way except ones return value will be the opposite of the other.
So, it doesn't sound right to write the same code twice to only return a different value. I'd like to know how I can call one custom validator from another.
Here's my code for the unique
validator:
<?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
should work like this:
<?php
Validator::add('exists', function($value, $rule, $options) {
$model = $options['model'];
return !$model::unique($value, $rule, $options);
});
?>
But obviously, it can't be done that way. Would I have to define the validation function as an anonymous function, assign it to a variable and pass that in instead of the closure?
Or is there a way I can call unique
from within exists
?
The anonymous function method would work. And then you could use that variable in another anonymous function you define for the 'exists' validator. Here's another idea that incorporates it into 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's probably an update
$conditions[$primary] = array('!=' => $options['values'][$primary]);
}
$exists = $model::count($conditions);
return ($exists) ? false : true;
}
}
?>