Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Respect validation multiple custom error messages

How do I have multiple custom errors messages with Respect Validation.

I have some input that I want to validate against multiple validators. And I want a custom error message for each validation.

This is what I tried:

try {
    Respect\Validation\Validator::create()
        ->key('foo',
            v::length(20)->setName('bar')->setTemplate('Custom length message.')
             ->alnum()->setName('baz')->setTemplate('Custom alnum message.')
        )
        ->assert([
            'foo' => 'Hello, world!',
        ]);
} catch (Respect\Validation\Exceptions\ValidationException $exception) {
    $errors = $exception->findMessages([
        'bar',
        'baz',
    ]);
    var_dump($errors);
}

The output is:

array (size=2)
  'bar' => string '' (length=0)
  'baz' => string 'Custom alnum message.' (length=21)

I expected it to output both custom error messages.

Idealy I could get an array of messages for 1 input like:

var_dump($exception->findMessages(['foo']));

Would give me:

array (size=1)
  'foo' => 
    array (size=2)
      0 => string 'Custom length message.' (length=22)
      1 => string 'Custom alnum message.' (length=21)

This question seems like tumble weed.

like image 822
Petah Avatar asked Mar 12 '13 01:03

Petah


1 Answers

You can not chain them together and get the custom message, because the last custom message you call will simply be assigned to the ruleset as opposed to he individual rules due to the implementation of the chaining.

To demonstrated this, I cloned it from git, created a bin directory, and modified your sample slightly with this test.php

<?php
set_include_path(implode(PATH_SEPARATOR, array(
  realpath('../library')
)));

function __autoload($class_name) {
    include $class_name . '.php';
}

use Respect\Validation\Validator as v;

try {
    $chained = Respect\Validation\Validator::create()
        ->key('foo',
            v::length(20)->setName('bar')->setTemplate('Custom length message.')
             ->alnum()->setName('baz')->setTemplate('Custom alnum message.')
        );

    print_r($chained);

    $chained->assert(array(
            'foo' => 'Hello, world!',
        ));

} catch (Respect\Validation\Exceptions\ValidationException $exception) {
    $errors = $exception->findMessages(array(
        'bar',
        'baz',
    ));
    var_dump($errors);
}

the print_r($chained) shows us:

Respect\Validation\Validator Object
(
    [rules:protected] => Array
        (
            [00000000791c0e000000000030f3f15e] => Respect\Validation\Rules\Key Object
                (
                    [mandatory] => 1
                    [reference] => foo
                    [validator] => Respect\Validation\Validator Object
                        (
                            [rules:protected] => Array
                                (
                                    [00000000791c0e030000000030f3f15e] => Respect\Validation\Rules\Length Object
                                        (
                                            [minValue] => 20
                                            [maxValue] =>
                                            [inclusive] => 1
                                            [name:protected] =>
                                            [template:protected] =>
                                        )

                                    [00000000791c0e020000000030f3f15e] => Respect\Validation\Rules\Alnum Object
                                        (
                                            [additionalChars] =>
                                            [stringFormat] => /^(\s|[a-zA-Z0-9])*$/
                                            [name:protected] =>
                                            [template:protected] =>
                                        )

                                )

                            [name:protected] => baz
                            [template:protected] => Custom alnum message.
                        )

                    [name:protected] => foo
                    [template:protected] =>
                )

        )

    [name:protected] =>
    [template:protected] =>
)

You may notice that the ruleset pick up the last name and well as the last template passed in, and that neither of the actual validation objects got the Name or the Template. I don't see any way in the library to actually do what you are attempting to do.

So I decided to make a way. In my ../bin directory I created this class, extending the Valditor class.

<?php
use Respect\Validation\Validator as v;
class BubbaValidator extends v {

    public function getRuleset($rulename = null){
        if (is_null($rulename)) return $this->rules;
        foreach ($this->rules as $rule){
            if ($rule->getName() == $rulename){
                return $rule;
            }
        }
    }

    public function getValidatorRules($rulesetName, $ruleType=null){
        $ruleset = $this->getRuleset($rulesetName);
        $validators = $ruleset->validator;

        if (is_null($ruleType)){
            return $validators;
        }

        foreach ($validators->rules as $key=>$validator){
            if (get_class($validator) === 'Respect\Validation\Rules\\'.$ruleType){
                $validator->name = "bar";
                $validator->template = "bubba rocks";
                $validators->rules[$key]->name = "bar";
                $validators->rules[$key]->template = "bubba rocks";
                return $validator;
            }
        }
    }

    public function setValidatorRuleName($rulesetName, $ruleType, $name){
        $ruleset = $this->getRuleset($rulesetName);
        $validators = $ruleset->validator;
        foreach ($validators->rules as $key=>$validator){
            if (get_class($validator) === 'Respect\Validation\Rules\\'.$ruleType){
                $validators->rules[$key]->name = $name;
                return $validator;
            }
        }
    }

    public function setValidatorRuleTemplate($rulesetName, $ruleType, $template){
        $ruleset = $this->getRuleset($rulesetName);
        $validators = $ruleset->validator;
        foreach ($validators->rules as $key=>$validator){
            if (get_class($validator) === 'Respect\Validation\Rules\\'.$ruleType){
                $validators->rules[$key]->template = $template;
                return $validator;
            }
        }
    }

}

then I modifed the script and ran it

<?php
set_include_path(implode(PATH_SEPARATOR, array(
  realpath('../library'),
  realpath(__DIR__)
)));

function __autoload($class_name) {
    include $class_name . '.php';
}

use BubbaValidator as v;

try {
    $chained = new BubbaValidator();
    $chained->key('foo',
            v::length(20)->setName('bar')->setTemplate('Custom length message.')
             ->alnum()->setName('baz')->setTemplate('Custom alnum message.')
        );

    $chained->setValidatorRuleName('foo', 'Alnum', 'baz');
    $chained->setValidatorRuleTemplate('foo', 'Alnum', 'Bubba\'s Custom Alnum!');
    $chained->setValidatorRuleName('foo', 'Length', 'bar');
    $chained->setValidatorRuleTemplate('foo', 'Length', 'Bubba\'s Custom Length!');

    $chained->assert(array(
            'foo' => 'Hello, world!',
        ));

} catch (Respect\Validation\Exceptions\ValidationException $exception) {
    $errors = $exception->findMessages(array(
        'bar',
        'baz',
    ));
    var_dump($errors);
}

to finally get this output:

  D:\Users\Bubba\git\Validation\bin>php test.php 
  array(2) {
    ["bar"]=> 
   string(22) "Bubba's Custom Length!" 
    ["baz"]=>   
    string(21) "Custom alnum message." }

That was fun!

like image 169
bubba Avatar answered Oct 14 '22 11:10

bubba