Implements: ArrayAccess
Array and variable validation.
Class declared in SYSPATH/classes/validation.php on line 3.
$_bound
$_data
$_empty_rules
$_errors
$_labels
$_rulesSets the unique "any field" key and creates an ArrayObject from the passed array.
array
$array
required - Array to validatevoid
public function __construct(array $array)
{
$this->_data = $array;
}
Returns the array representation of the current object. Deprecated in favor of Validation::data
array
public function as_array()
{
return $this->_data;
}
Bind a value to a parameter definition.
// This allows you to use :model in the parameter definition of rules
$validation->bind(':model', $model)
->rule('status', 'valid_status', array(':model'));
string
$key
required - Variable name or an array of variablesmixed
$value
= NULL - Value$this
public function bind($key, $value = NULL)
{
if (is_array($key))
{
foreach ($key as $name => $value)
{
$this->_bound[$name] = $value;
}
}
else
{
$this->_bound[$key] = $value;
}
return $this;
}
Executes all validation rules. This should typically be called within an if/else block.
if ($validation->check())
{
// The data is valid, do something here
}
boolean
public function check()
{
if (Kohana::$profiling === TRUE)
{
// Start a new benchmark
$benchmark = Profiler::start('Validation', __FUNCTION__);
}
// New data set
$data = $this->_errors = array();
// Store the original data because this class should not modify it post-validation
$original = $this->_data;
// Get a list of the expected fields
$expected = Arr::merge(array_keys($original), array_keys($this->_labels));
// Import the rules locally
$rules = $this->_rules;
foreach ($expected as $field)
{
// Use the submitted value or NULL if no data exists
$data[$field] = Arr::get($this, $field);
if (isset($rules[TRUE]))
{
if ( ! isset($rules[$field]))
{
// Initialize the rules for this field
$rules[$field] = array();
}
// Append the rules
$rules[$field] = array_merge($rules[$field], $rules[TRUE]);
}
}
// Overload the current array with the new one
$this->_data = $data;
// Remove the rules that apply to every field
unset($rules[TRUE]);
// Bind the validation object to :validation
$this->bind(':validation', $this);
// Bind the data to :data
$this->bind(':data', $this->_data);
// Execute the rules
foreach ($rules as $field => $set)
{
// Get the field value
$value = $this[$field];
// Bind the field name and value to :field and :value respectively
$this->bind(array
(
':field' => $field,
':value' => $value,
));
foreach ($set as $array)
{
// Rules are defined as array($rule, $params)
list($rule, $params) = $array;
foreach ($params as $key => $param)
{
if (is_string($param) AND array_key_exists($param, $this->_bound))
{
// Replace with bound value
$params[$key] = $this->_bound[$param];
}
}
// Default the error name to be the rule (except array and lambda rules)
$error_name = $rule;
if (is_array($rule))
{
// Allows rule('field', array(':model', 'some_rule'));
if (is_string($rule[0]) AND array_key_exists($rule[0], $this->_bound))
{
// Replace with bound value
$rule[0] = $this->_bound[$rule[0]];
}
// This is an array callback, the method name is the error name
$error_name = $rule[1];
$passed = call_user_func_array($rule, $params);
}
elseif ( ! is_string($rule))
{
// This is a lambda function, there is no error name (errors must be added manually)
$error_name = FALSE;
$passed = call_user_func_array($rule, $params);
}
elseif (method_exists('Valid', $rule))
{
// Use a method in this object
$method = new ReflectionMethod('Valid', $rule);
// Call static::$rule($this[$field], $param, ...) with Reflection
$passed = $method->invokeArgs(NULL, $params);
}
elseif (strpos($rule, '::') === FALSE)
{
// Use a function call
$function = new ReflectionFunction($rule);
// Call $function($this[$field], $param, ...) with Reflection
$passed = $function->invokeArgs($params);
}
else
{
// Split the class and method of the rule
list($class, $method) = explode('::', $rule, 2);
// Use a static method call
$method = new ReflectionMethod($class, $method);
// Call $Class::$method($this[$field], $param, ...) with Reflection
$passed = $method->invokeArgs(NULL, $params);
}
// Ignore return values from rules when the field is empty
if ( ! in_array($rule, $this->_empty_rules) AND ! Valid::not_empty($value))
continue;
if ($passed === FALSE AND $error_name !== FALSE)
{
// Add the rule to the errors
$this->error($field, $error_name, $params);
// This field has an error, stop executing rules
break;
}
elseif (isset($this->_errors[$field]))
{
// The callback added the error manually, stop checking rules
break;
}
}
}
// Restore the data to its original form
$this->_data = $original;
if (isset($benchmark))
{
// Stop benchmarking
Profiler::stop($benchmark);
}
return empty($this->_errors);
}
Copies the current rules to a new array.
$copy = $array->copy($new_data);
array
$array
required - New data setValidation
public function copy(array $array)
{
// Create a copy of the current validation set
$copy = clone $this;
// Replace the data set
$copy->_data = $array;
return $copy;
}
Returns the array of data to be validated.
array
public function data()
{
return $this->_data;
}
Add an error to a field.
string
$field
required - Field namestring
$error
required - Error messagearray
$params
= NULL - $params$this
public function error($field, $error, array $params = NULL)
{
$this->_errors[$field] = array($error, $params);
return $this;
}
Returns the error messages. If no file is specified, the error message will be the name of the rule that failed. When a file is specified, the message will be loaded from "field/rule", or if no rule-specific message exists, "field/default" will be used. If neither is set, the returned message will be "file/field/rule".
By default all messages are translated using the default language. A string can be used as the second parameter to specified the language that the message was written in.
// Get errors from messages/forms/login.php
$errors = $Validation->errors('forms/login');
string
$file
= NULL - File to load error messages frommixed
$translate
= bool TRUE - Translate the messagearray
public function errors($file = NULL, $translate = TRUE)
{
if ($file === NULL)
{
// Return the error list
return $this->_errors;
}
// Create a new message list
$messages = array();
foreach ($this->_errors as $field => $set)
{
list($error, $params) = $set;
// Get the label for this field
$label = $this->_labels[$field];
if ($translate)
{
if (is_string($translate))
{
// Translate the label using the specified language
$label = __($label, NULL, $translate);
}
else
{
// Translate the label
$label = __($label);
}
}
// Start the translation values list
$values = array(
':field' => $label,
':value' => Arr::get($this, $field),
);
if (is_array($values[':value']))
{
// All values must be strings
$values[':value'] = implode(', ', Arr::flatten($values[':value']));
}
if ($params)
{
foreach ($params as $key => $value)
{
if (is_array($value))
{
// All values must be strings
$value = implode(', ', Arr::flatten($value));
}
elseif (is_object($value))
{
// Objects cannot be used in message files
continue;
}
// Check if a label for this parameter exists
if (isset($this->_labels[$value]))
{
// Use the label as the value, eg: related field name for "matches"
$value = $this->_labels[$value];
if ($translate)
{
if (is_string($translate))
{
// Translate the value using the specified language
$value = __($value, NULL, $translate);
}
else
{
// Translate the value
$value = __($value);
}
}
}
// Add each parameter as a numbered value, starting from 1
$values[':param'.($key + 1)] = $value;
}
}
if ($message = Kohana::message($file, "{$field}.{$error}") AND is_string($message))
{
// Found a message for this field and error
}
elseif ($message = Kohana::message($file, "{$field}.default") AND is_string($message))
{
// Found a default message for this field
}
elseif ($message = Kohana::message($file, $error) AND is_string($message))
{
// Found a default message for this error
}
elseif ($message = Kohana::message('validation', $error) AND is_string($message))
{
// Found a default message for this error
}
else
{
// No message exists, display the path expected
$message = "{$file}.{$field}.{$error}";
}
if ($translate)
{
if (is_string($translate))
{
// Translate the message using specified language
$message = __($message, $values, $translate);
}
else
{
// Translate the message using the default language
$message = __($message, $values);
}
}
else
{
// Do not translate, just replace the values
$message = strtr($message, $values);
}
// Set the message for this field
$messages[$field] = $message;
}
return $messages;
}
Creates a new Validation instance.
array
$array
required - Array to use for validationValidation
public static function factory(array $array)
{
return new Validation($array);
}
Sets or overwrites the label name for a field.
string
$field
required - Field namestring
$label
required - Label$this
public function label($field, $label)
{
// Set the label for this field
$this->_labels[$field] = $label;
return $this;
}
Sets labels using an array.
array
$labels
required - List of field => label names$this
public function labels(array $labels)
{
$this->_labels = $labels + $this->_labels;
return $this;
}
Checks if key is set in array data. Implements ArrayAccess method.
string
$offset
required - Key to checkbool
- Whether the key is setpublic function offsetExists($offset)
{
return isset($this->_data[$offset]);
}
Gets a value from the array data. Implements ArrayAccess method.
string
$offset
required - Key to returnmixed
- Value from arraypublic function offsetGet($offset)
{
return $this->_data[$offset];
}
Throws an exception because Validation is read-only. Implements ArrayAccess method.
string
$offset
required - Key to setmixed
$value
required - Value to setvoid
public function offsetSet($offset, $value)
{
throw new Kohana_Exception('Validation objects are read-only.');
}
Throws an exception because Validation is read-only. Implements ArrayAccess method.
string
$offset
required - Key to unsetvoid
public function offsetUnset($offset)
{
throw new Kohana_Exception('Validation objects are read-only.');
}
Overwrites or appends rules to a field. Each rule will be executed once. All rules must be string names of functions method names. Parameters must match the parameters of the callback function exactly
Aliases you can use in callback parameters: - :validation - the validation object - :field - the field name - :value - the value of the field
// The "username" must not be empty and have a minimum length of 4
$validation->rule('username', 'not_empty')
->rule('username', 'min_length', array(':value', 4));
// The "password" field must match the "password_repeat" field
$validation->rule('password', 'matches', array(':validation', 'password', 'password_repeat'));
// Using closure (anonymous function)
$validation->rule('index',
function(Validation $array, $field, $value)
{
if ($value > 6 AND $value < 10)
{
$array->error($field, 'custom');
}
}
, array(':validation', ':field', ':value')
);
Errors must be added manually when using closures!
string
$field
required - Field namecallback
$rule
required - Valid PHP callback or closurearray
$params
= NULL - Extra parameters for the rule$this
public function rule($field, $rule, array $params = NULL)
{
if ($params === NULL)
{
// Default to array(':value')
$params = array(':value');
}
if ($field !== TRUE AND ! isset($this->_labels[$field]))
{
// Set the field label to the field name
$this->_labels[$field] = preg_replace('/[^\pL]+/u', ' ', $field);
}
// Store the rule and params for this rule
$this->_rules[$field][] = array($rule, $params);
return $this;
}
Add rules using an array.
string
$field
required - Field namearray
$rules
required - List of callbacks$this
public function rules($field, array $rules)
{
foreach ($rules as $rule)
{
$this->rule($field, $rule[0], Arr::get($rule, 1));
}
return $this;
}