Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

scenario-based validation in Phalcon ?


Do you know how to implement scenario-based validation in Phalcon, in similar way as it is in Yii ?

I am going to create an intermediate class to extend Model and implement scenario functionality in it... But may be it is present already, I just did not find??


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 = [

    protected $scenario;

    protected $validators;

     * Array of fields to skip validation on
     * @var unknown
    protected $_skipFields = array();

    public function initialize()

    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;

            if ($except && in_array($except, $this->scenario)) {

            if ($on && !in_array($on, $this->scenario)) {

            $validatorClass = $this->getValidatorClass($validator);
            foreach ($fields as $field) {
                // FLAGGED TO SKIP
                if (in_array($field, $this->_skipFields) ) {

                $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)




Hi jymboche, This is really good code, thanks a lot!! I'll put here a comment when test this and add something.


Hello jymboche!!

I have created a class, extended the one you provided above. Found some issues that might be interesting for someone reading this topic. From what I've found, scenario shall be an array assigned as

$mm->scenario = ['scenario1','scenario2'] ;

in this case the piece of code

if ($on && !in_array($on, $this->scenario))

will work only.

Next thing is, when a user overloads a function Rules(), he shall write the scenario as a string, but not array. So it shall look like

public function rules(){

    return [

        ['id', 'PresenceOf', 'on'=>'scenario1'],

        ['email', 'Email', 'on'=>'scenario2'],

        ['email', 'Uniqueness', 'message'=>'An item with this email already exists', 'on'=>'scenario2'],

        ['name', 'StringLength', 'min'=>3, 'max'=>20, 'on'=>'scenario2']



Thank you for the code!!


Awesome, glad you worked it out. When/if you've finished your class maybe consider adding it to the phalcon incubator repository:

I think a lot of users would like something similar to this in the phalcon core eventually. Thanks!

Yeah, an integrated scenario functionality could be usefull!

I'd rather prefer anyway a more object oriented approach to the problem instead and avoid the use of $validatorMap simply using the fully qualified namespace or a valid callable on the second parameter of the validator definition.

Thanks for the start!


I've had a change of philosophy over the past couple months. I've embraced using forms and form validation/sanitization and keep model validation to the bare minimum. It's a somewhat different approach than other frameworks but I've grown to like it.

Me too Jym! I use model validation just to ensure the right type on the persistent layer