Hey Dimonsky,
I too came from Yii and quite like how Yii handles validation. Here is a rough base model class I've been using. I haven't implemented all the features yet, but it mostly works for my purposes.
It lets you define a rules method in your model like this:
public function rules()
{
return [
['member_id', 'PresenceOf'],
['title', 'StringLength', 'min'=>5, 'max'=>50],
['title', 'Uniqueness', 'message'=>'An item with this title already exists'],
['description', 'StringLength', 'min'=>50, 'max'=>255],
['demo_url', 'Url'],
['status', 'Inclusionin', 'domain'=>[0, 1, 2, 3]],
['accept_terms', 'Inclusionin', 'domain'=>[0, 1]]
];
}
You can set a scenario just by doing $model->scenario = 'myscenario'; Or you can explicity skip fields by calling $model->skipValidation(array('title', 'description'))... which takes either a string or array.
On a side note, use at your own risk. I haven't tested the logic and I use $model->skipValidation() rather than setting scenarios. Heres the rough class:
use Phalcon\Mvc\Model\Message as Message;
class Model extends \Phalcon\Mvc\Model
{
protected $validatorMap = [
'Email'=>'Phalcon\Mvc\Model\Validator\Email',
'Exclusionin'=>'Phalcon\Mvc\Model\Validator\Exclusionin',
'Inclusionin'=>'Phalcon\Mvc\Model\Validator\Inclusionin',
'Numericality'=>'Phalcon\Mvc\Model\Validator\Numericality',
'PresenceOf'=>'Phalcon\Mvc\Model\Validator\PresenceOf',
'Regex'=>'Phalcon\Mvc\Model\Validator\Regex',
'StringLength'=>'Phalcon\Mvc\Model\Validator\StringLength',
'Uniqueness'=>'Phalcon\Mvc\Model\Validator\Uniqueness',
'Url'=>'Phalcon\Mvc\Model\Validator\Url',
'compare'=>'compare',
'default'=>'defaultValue'
];
protected $scenario;
protected $validators;
/**
* Array of fields to skip validation on
*
* @var unknown
*/
protected $_skipFields = array();
public function initialize()
{
$this->setup(['notNullValidations'=>FALSE]);
}
protected function rules()
{
return array();
}
public function skipValidation($field)
{
$type = gettype($field);
if ($type == "array") {
foreach ($field as $name) {
$this->_skipFields[] = (string) $name;
}
} else {
$this->_skipFields[] = (string) $field;
}
}
protected function validation()
{
foreach ($this->rules() as $rule) {
$fields = explode(',', $rule[0]);
if (!isset($rule[0], $rule[1])) {
throw new Phalcon\Exception('Invalid model rule');
}
$validator = $rule[1];
$args = array_slice($rule, 2);
$on = isset($rule['on'])? (array)$rule['on'] : false;
$except = isset($rule['except'])? (array)$rule['except'] : false;
// EXCEPT FLAG PRESENT, AND SCENARIO MATCHES, DONT VALIDATE
if ($except && in_array($except, $this->scenario)) {
continue;
}
// ON FLAG PRESENT, BUT SCENARIO DOESNT MATCH, DONT VALIDATE
if ($on && !in_array($on, $this->scenario)) {
continue;
}
$validatorClass = $this->getValidatorClass($validator);
foreach ($fields as $field) {
// FLAGGED TO SKIP
if (in_array($field, $this->_skipFields) ) {
continue;
}
$args['field'] = trim($field);
if (method_exists($this, $validatorClass)) {
$this->{$validatorClass}($field, $args);
} else {
$this->validate( new $validatorClass($args) );
}
}
}
return !$this->validationHasFailed() == true;
}
private function getValidatorClass($validator = "")
{
return isset($this->validatorMap[$validator])? $this->validatorMap[$validator] : $validator;
}
private function compare($field, $args)
{
if ( !isset($args['with']) || $this->{$field} !== $this->{$args['with']}) {
$this->appendMessage(new Message("{$field} doesn't match", $field));
return false;
}
return true;
}
public function defaultValue($field, $args)
{
}
}