Why are validation shown against value rather than field name? #86

Closed
silentworks opened this Issue Oct 10, 2012 · 65 comments

Comments

Projects
None yet
@silentworks

Currently If I try to validate $_POST['username'] I get the value in the validation message rather than the name username?

try {
    v::alnum()
        ->noWhitespace()
        ->length(4,22)
        ->check($_POST['username']);
} catch (\InvalidArgumentException $e) {
    var_dump($e->getMainMessage());
}

result

"" must not contain whitespace

what I was expecting

"username" must not contain whitespace
@augustohp

This comment has been minimized.

Show comment Hide comment
@augustohp

augustohp Oct 10, 2012

Owner

Actually, what you see is the value that failed validation. You can use the method setName() in a Validator to set its name, it will be like that:

try {
    v::alnum()
        ->noWhitespace()
        ->length(4,22)
        ->setName('username')
        ->check($_POST['username']);
} catch (\InvalidArgumentException $e) {
    var_dump($e->getMainMessage());
}
Owner

augustohp commented Oct 10, 2012

Actually, what you see is the value that failed validation. You can use the method setName() in a Validator to set its name, it will be like that:

try {
    v::alnum()
        ->noWhitespace()
        ->length(4,22)
        ->setName('username')
        ->check($_POST['username']);
} catch (\InvalidArgumentException $e) {
    var_dump($e->getMainMessage());
}
@silentworks

This comment has been minimized.

Show comment Hide comment
@silentworks

silentworks Oct 10, 2012

I thought that would have done the trick but it actually does nothing for me, message remains the same.

I thought that would have done the trick but it actually does nothing for me, message remains the same.

@drgomesp

This comment has been minimized.

Show comment Hide comment
@drgomesp

drgomesp Oct 10, 2012

Member

+1.

I do agree, though, that we shouldn't have to manually set the name for the specific validator.

Member

drgomesp commented Oct 10, 2012

+1.

I do agree, though, that we shouldn't have to manually set the name for the specific validator.

@silentworks

This comment has been minimized.

Show comment Hide comment
@silentworks

silentworks Oct 10, 2012

I have tried this on both the develop branch and the 0.4.* version.

I have tried this on both the develop branch and the 0.4.* version.

@augustohp

This comment has been minimized.

Show comment Hide comment
@augustohp

augustohp Oct 10, 2012

Owner

Sorry about that, now I made sure to check the code before posting for a solution.

try {
    $username = '';
    v::alnum()
     ->noWhitespace()
     ->length(4,22)
     ->setName('username')
     ->assert($username);
} catch (\InvalidArgumentException $e) {
    print_r($e->getFullMessage());
    echo PHP_EOL;
}

You have to use the method getFullMessage in the Exception. This method is only available when the validation is done using assert as it can be seen on the documentation.

Let me know if this works like you want.
We will try to make this more clear into the README.md.

@drgomesp How do you propose we get a name of a validator? I don't have many ideas on this. =(

Owner

augustohp commented Oct 10, 2012

Sorry about that, now I made sure to check the code before posting for a solution.

try {
    $username = '';
    v::alnum()
     ->noWhitespace()
     ->length(4,22)
     ->setName('username')
     ->assert($username);
} catch (\InvalidArgumentException $e) {
    print_r($e->getFullMessage());
    echo PHP_EOL;
}

You have to use the method getFullMessage in the Exception. This method is only available when the validation is done using assert as it can be seen on the documentation.

Let me know if this works like you want.
We will try to make this more clear into the README.md.

@drgomesp How do you propose we get a name of a validator? I don't have many ideas on this. =(

@silentworks

This comment has been minimized.

Show comment Hide comment
@silentworks

silentworks Oct 10, 2012

@augustohp This still yeild the same as before except that I now have the results in a list.

result

string '\-These rules must pass for username
  |-"" must not contain whitespace
  \-"" must have a length between 4 and 22' (length=116)

I was expecting this

string '\-These rules must pass for username
  |-"username" must not contain whitespace
  \-"username" must have a length between 4 and 22' (length=116)

@augustohp This still yeild the same as before except that I now have the results in a list.

result

string '\-These rules must pass for username
  |-"" must not contain whitespace
  \-"" must have a length between 4 and 22' (length=116)

I was expecting this

string '\-These rules must pass for username
  |-"username" must not contain whitespace
  \-"username" must have a length between 4 and 22' (length=116)
@drgomesp

This comment has been minimized.

Show comment Hide comment
@drgomesp

drgomesp Oct 11, 2012

Member

@augustohp I would just dump the value being validated at the time.

For me, it makes a lot more sense than manually setting a name for it.

But I'm not sure this would be the best approach, though.

try {
    $username = '';
    v::alnum()
     ->noWhitespace()
     ->length(4,22)
     ->assert('Daniel Ribeiro');
} catch (\InvalidArgumentException $e) {
    print_r($e->getFullMessage());
    echo PHP_EOL;
}

The expected result would be:

"Daniel Ribeiro" must not contain whitespace
Member

drgomesp commented Oct 11, 2012

@augustohp I would just dump the value being validated at the time.

For me, it makes a lot more sense than manually setting a name for it.

But I'm not sure this would be the best approach, though.

try {
    $username = '';
    v::alnum()
     ->noWhitespace()
     ->length(4,22)
     ->assert('Daniel Ribeiro');
} catch (\InvalidArgumentException $e) {
    print_r($e->getFullMessage());
    echo PHP_EOL;
}

The expected result would be:

"Daniel Ribeiro" must not contain whitespace
@silentworks

This comment has been minimized.

Show comment Hide comment
@silentworks

silentworks Oct 11, 2012

Guys this make no sense to me at all, why would I want my message to say my value must not contain whitespace rather than the field that submitted the value.

How would you associate the validation to a field in a form then?

If I am validating the username, I want to tell the user that Username field much not contain whitespace not the value of the username field.

Guys this make no sense to me at all, why would I want my message to say my value must not contain whitespace rather than the field that submitted the value.

How would you associate the validation to a field in a form then?

If I am validating the username, I want to tell the user that Username field much not contain whitespace not the value of the username field.

@drgomesp

This comment has been minimized.

Show comment Hide comment
@drgomesp

drgomesp Oct 11, 2012

Member

@silentworks there is really no magic on this, mate.

Take this as an example:

try {
    $username = "Daniel Ribeiro";
    v::alnum()
     ->noWhitespace()
     ->length(4,22)
     ->assert($username);
} catch (\InvalidArgumentException $e) {
    print_r($e->getFullMessage());
    echo PHP_EOL;
}

Unless you explicity tell the validator, like @augustohp said, there is no way it is going to know what is being treated.

That's why I suggested the value as the return that makes more sense.

Member

drgomesp commented Oct 11, 2012

@silentworks there is really no magic on this, mate.

Take this as an example:

try {
    $username = "Daniel Ribeiro";
    v::alnum()
     ->noWhitespace()
     ->length(4,22)
     ->assert($username);
} catch (\InvalidArgumentException $e) {
    print_r($e->getFullMessage());
    echo PHP_EOL;
}

Unless you explicity tell the validator, like @augustohp said, there is no way it is going to know what is being treated.

That's why I suggested the value as the return that makes more sense.

@silentworks

This comment has been minimized.

Show comment Hide comment
@silentworks

silentworks Oct 11, 2012

@drgomesp I think you are still missing what I am saying. I don't want the validation to return a value in the message string, I want it to return the field name. I am using setName but it still doesn't use the name in the validation message beside the line that say "This rule must pass for "

result

string '\-These rules must pass for username
  |-"" must not contain whitespace
  \-"" must have a length between 4 and 22' (length=116)

what I expect

string '\-These rules must pass for username
  |-"username" must not contain whitespace
  \-"username" must have a length between 4 and 22' (length=116)

@drgomesp I think you are still missing what I am saying. I don't want the validation to return a value in the message string, I want it to return the field name. I am using setName but it still doesn't use the name in the validation message beside the line that say "This rule must pass for "

result

string '\-These rules must pass for username
  |-"" must not contain whitespace
  \-"" must have a length between 4 and 22' (length=116)

what I expect

string '\-These rules must pass for username
  |-"username" must not contain whitespace
  \-"username" must have a length between 4 and 22' (length=116)
@drgomesp

This comment has been minimized.

Show comment Hide comment
@drgomesp

drgomesp Oct 11, 2012

Member

@silentworks, ok, I did missunderstood.

Did you try using getFullMessage() instead of getMainMessage()?

Member

drgomesp commented Oct 11, 2012

@silentworks, ok, I did missunderstood.

Did you try using getFullMessage() instead of getMainMessage()?

@silentworks

This comment has been minimized.

Show comment Hide comment
@silentworks

silentworks Oct 11, 2012

@drgomesp I tried both, all give same result, this seem to have not been considered when the library was written or if it was the docs doesn't say how to do it.

@drgomesp I tried both, all give same result, this seem to have not been considered when the library was written or if it was the docs doesn't say how to do it.

@alganet

This comment has been minimized.

Show comment Hide comment
@alganet

alganet Oct 11, 2012

Owner

Looks broken indeed. Had similar problems with setName() and check() not reporting the proper identifiers for exceptions. The identifier is a value that the validator flow identifies as the best human representation for a given validation constrain (in the key() case, should be the key name as @silentworks expected).

I'll take a look at this as soon as possible and report over here. If anyone's interested in fixing this probably the problem is in the ValidationException class or one of its derivates.

Owner

alganet commented Oct 11, 2012

Looks broken indeed. Had similar problems with setName() and check() not reporting the proper identifiers for exceptions. The identifier is a value that the validator flow identifies as the best human representation for a given validation constrain (in the key() case, should be the key name as @silentworks expected).

I'll take a look at this as soon as possible and report over here. If anyone's interested in fixing this probably the problem is in the ValidationException class or one of its derivates.

@wesleyvicthor

This comment has been minimized.

Show comment Hide comment
@wesleyvicthor

wesleyvicthor Oct 11, 2012

Member

Actually the problem is related with AbstractComposite.

The setName() method just sets the name of a group of rules, thus this group have a name:

v::allOf(v::alnum()->noWhitespace())->setName('POST data')->assert($_POST['username']);

When we try to set the name of a specific rule doesn't work because, the interface does not provide the access to the current rule.
That's occurs because the Validator doesn't return the added rule. It returns a self instance, so: Validator < AllOf < AbstractComposite < AbstractRule.

To fix this I propose to add the name parameter in the constructor of AbstractRule. The interface will looks like:

v::alnum()
    ->noWhitespace('username')
    ->length(4,22)
    ->check($_POST['username']);

@alganet @augustohp guys ?

Member

wesleyvicthor commented Oct 11, 2012

Actually the problem is related with AbstractComposite.

The setName() method just sets the name of a group of rules, thus this group have a name:

v::allOf(v::alnum()->noWhitespace())->setName('POST data')->assert($_POST['username']);

When we try to set the name of a specific rule doesn't work because, the interface does not provide the access to the current rule.
That's occurs because the Validator doesn't return the added rule. It returns a self instance, so: Validator < AllOf < AbstractComposite < AbstractRule.

To fix this I propose to add the name parameter in the constructor of AbstractRule. The interface will looks like:

v::alnum()
    ->noWhitespace('username')
    ->length(4,22)
    ->check($_POST['username']);

@alganet @augustohp guys ?

@drgomesp

This comment has been minimized.

Show comment Hide comment
@drgomesp

drgomesp Oct 11, 2012

Member

It's a good proposal, @wesleyvicthor, but it doesn't look very semantic to me.

Still the problem should be resolved.

Member

drgomesp commented Oct 11, 2012

It's a good proposal, @wesleyvicthor, but it doesn't look very semantic to me.

Still the problem should be resolved.

@silentworks

This comment has been minimized.

Show comment Hide comment
@silentworks

silentworks Oct 11, 2012

@wesleyvicthor this would mean I would have to add a name to all my rules, which removes the whole DRYness of Respect\Validation. As @drgomesp said this doesn't fix the issue.

I am currently looking into the issue and will do a pull request once I nail it.

Can someone remove the FAQ label and label this as a Bug please.

@wesleyvicthor this would mean I would have to add a name to all my rules, which removes the whole DRYness of Respect\Validation. As @drgomesp said this doesn't fix the issue.

I am currently looking into the issue and will do a pull request once I nail it.

Can someone remove the FAQ label and label this as a Bug please.

@alganet

This comment has been minimized.

Show comment Hide comment
@alganet

alganet Oct 11, 2012

Owner

@silentworks thank you very much!

I've also took a better look at the sample and thought on using something like this:

try {
    v::key(
        'username', 
        v::alnum()
         ->noWhitespace()
         ->length(4,22)
         ->check($_POST));
} catch (\InvalidArgumentException $e) {
    var_dump($e->getMainMessage());
}

Could you please test this?

@wesleyvicthor actually, the allOf validator chain can handle nested validators. That's exactly what getFullMessage() does. Check the AbstractNestedException and AbstractGroupedException, their interaction with the ExceptionIterator can ommit redundant and overnested validators (ex: v::allOf(v::allOf(v::allOf(v::bool())))) and don't report validation messages for irrelevant conteiners. Unfortunately, check() doesn't iterate over exceptions and some goodies added there aren't being applied outside this case.

Owner

alganet commented Oct 11, 2012

@silentworks thank you very much!

I've also took a better look at the sample and thought on using something like this:

try {
    v::key(
        'username', 
        v::alnum()
         ->noWhitespace()
         ->length(4,22)
         ->check($_POST));
} catch (\InvalidArgumentException $e) {
    var_dump($e->getMainMessage());
}

Could you please test this?

@wesleyvicthor actually, the allOf validator chain can handle nested validators. That's exactly what getFullMessage() does. Check the AbstractNestedException and AbstractGroupedException, their interaction with the ExceptionIterator can ommit redundant and overnested validators (ex: v::allOf(v::allOf(v::allOf(v::bool())))) and don't report validation messages for irrelevant conteiners. Unfortunately, check() doesn't iterate over exceptions and some goodies added there aren't being applied outside this case.

@silentworks

This comment has been minimized.

Show comment Hide comment
@silentworks

silentworks Oct 11, 2012

@augustohp I have tested and I now get

"Array" must contain only letters...

Have you tested it? Are there any particular requirements for Respect\Validation? Any PHP extension that should be on or any settings?

@augustohp I have tested and I now get

"Array" must contain only letters...

Have you tested it? Are there any particular requirements for Respect\Validation? Any PHP extension that should be on or any settings?

@silentworks

This comment has been minimized.

Show comment Hide comment
@silentworks

silentworks Oct 17, 2012

Ok so it seems this work differently from how the documentation describes it and different to all the examples given. I have found a solution in doing this:

try {
    v::alnum()
        ->noWhitespace()
        ->length(4,22)
        ->check($_POST['username']);
} catch (\InvalidArgumentException $e) {
    var_dump($e->setName('Username')->getMainMessage());
}

However this becomes a problem when you want to validate 2 or more fields, since you can have only 1 catch. So if I wanted to validate a username and password.

try {
    v::alnum()
        ->noWhitespace()
        ->length(4,22)
        ->check($_POST['username']);

    v::alnum()
        ->noWhitespace()
        ->length(5,26)
        ->check($_POST['password']);
} catch (\InvalidArgumentException $e) {
    var_dump($e->setName('Username')->getMainMessage());
}

There is no way for me to setName for each separately.

Ok so it seems this work differently from how the documentation describes it and different to all the examples given. I have found a solution in doing this:

try {
    v::alnum()
        ->noWhitespace()
        ->length(4,22)
        ->check($_POST['username']);
} catch (\InvalidArgumentException $e) {
    var_dump($e->setName('Username')->getMainMessage());
}

However this becomes a problem when you want to validate 2 or more fields, since you can have only 1 catch. So if I wanted to validate a username and password.

try {
    v::alnum()
        ->noWhitespace()
        ->length(4,22)
        ->check($_POST['username']);

    v::alnum()
        ->noWhitespace()
        ->length(5,26)
        ->check($_POST['password']);
} catch (\InvalidArgumentException $e) {
    var_dump($e->setName('Username')->getMainMessage());
}

There is no way for me to setName for each separately.

@nickl-

This comment has been minimized.

Show comment Hide comment
@nickl-

nickl- Oct 18, 2012

Member

Wow busy busy busy =) awesomeness!

Member

nickl- commented Oct 18, 2012

Wow busy busy busy =) awesomeness!

@silentworks

This comment has been minimized.

Show comment Hide comment
@silentworks

silentworks Oct 18, 2012

I am close to a solution I think, the current issue is around each rule resetting $this->name in the AbstractRule class so by the time the getName_ method is called $this->name is blank. Its not persisting. I am thinking of calling the __ ValidationException__ setName method inside of the AbstractRule setName method, but I will have to modify the ValidationException class in order to call existing instance rather than a new one each time.

I hope all this make sense, if not I will make the change and send a pull request.

I am close to a solution I think, the current issue is around each rule resetting $this->name in the AbstractRule class so by the time the getName_ method is called $this->name is blank. Its not persisting. I am thinking of calling the __ ValidationException__ setName method inside of the AbstractRule setName method, but I will have to modify the ValidationException class in order to call existing instance rather than a new one each time.

I hope all this make sense, if not I will make the change and send a pull request.

@wesleyvicthor

This comment has been minimized.

Show comment Hide comment
@wesleyvicthor

wesleyvicthor Oct 18, 2012

Member

@silentworks it is not directly related with setName or getName. I explained it above. You are not setting the name to the right object.

If you want to test groups, you can use AllOf. With your example, the AllOf method should work.

I know it is not the better approach but until we fix these bugs, the example below can fix your problem.

try {
    v::allOf(
         v::attribute('username', v::string()->length(4,22)->noWhitespace())->setName('username'),
         v::attribute('password', v::string()->length(5,26)->noWhitespace())->setName('password')
    )->setName('User Validation')->assert($_POST);
} catch (\InvalidArgumentException $e) {
    var_dump($e->getFullMessage());
}

I think we have some design issues. @alganet @augustohp

Member

wesleyvicthor commented Oct 18, 2012

@silentworks it is not directly related with setName or getName. I explained it above. You are not setting the name to the right object.

If you want to test groups, you can use AllOf. With your example, the AllOf method should work.

I know it is not the better approach but until we fix these bugs, the example below can fix your problem.

try {
    v::allOf(
         v::attribute('username', v::string()->length(4,22)->noWhitespace())->setName('username'),
         v::attribute('password', v::string()->length(5,26)->noWhitespace())->setName('password')
    )->setName('User Validation')->assert($_POST);
} catch (\InvalidArgumentException $e) {
    var_dump($e->getFullMessage());
}

I think we have some design issues. @alganet @augustohp

@silentworks

This comment has been minimized.

Show comment Hide comment
@silentworks

silentworks Oct 18, 2012

@wesleyvicthor your solution is not a fix as this still leaves the user in the blind as to which rules are failing.

The result I get is this:

These rules must pass for User Validation |
- These rules must pass for user name
- These rules must pass for password

There are no indication as to what these rules are.

@wesleyvicthor your solution is not a fix as this still leaves the user in the blind as to which rules are failing.

The result I get is this:

These rules must pass for User Validation |
- These rules must pass for user name
- These rules must pass for password

There are no indication as to what these rules are.

@silentworks

This comment has been minimized.

Show comment Hide comment
@silentworks

silentworks Nov 26, 2012

No update on this one, its would seem even though it is a critical bug, its not being addressed.

No update on this one, its would seem even though it is a critical bug, its not being addressed.

@alganet

This comment has been minimized.

Show comment Hide comment
@alganet

alganet Nov 26, 2012

Owner

Hey @silentworks, sorry for the delay! Have you tried my solution?

Also, @wesleyvicthor solution has a little problem, it should be v::key (for array keys) and not v::attribute (for object attributes). Maybe changing that could make it run properly and report nested exceptions better.

Owner

alganet commented Nov 26, 2012

Hey @silentworks, sorry for the delay! Have you tried my solution?

Also, @wesleyvicthor solution has a little problem, it should be v::key (for array keys) and not v::attribute (for object attributes). Maybe changing that could make it run properly and report nested exceptions better.

@silentworks

This comment has been minimized.

Show comment Hide comment
@silentworks

silentworks Dec 4, 2012

I have tried all solutions and none work. If possible can someone provide me with a working sample code that will output messages based upon field name.

I have decided in the short term to next two try and catch statements to accomplish what I am trying to do at the moment.

I have tried all solutions and none work. If possible can someone provide me with a working sample code that will output messages based upon field name.

I have decided in the short term to next two try and catch statements to accomplish what I am trying to do at the moment.

@wesleyvicthor

This comment has been minimized.

Show comment Hide comment
@wesleyvicthor

wesleyvicthor Dec 4, 2012

Member
try {
        v::allOf(
            v::key('email', v::email()),
            v::key('passw', v::notEmpty()->noWhitespace()->length(4, 8))
        )->assert($_POST);

} catch (\InvalidArgumentException $e) {
    $errors = $e->findMessages(
        array(
            'email' => 'email error',
            'passw' => 'password error',
        )
    );
}

have you tried this ?

Member

wesleyvicthor commented Dec 4, 2012

try {
        v::allOf(
            v::key('email', v::email()),
            v::key('passw', v::notEmpty()->noWhitespace()->length(4, 8))
        )->assert($_POST);

} catch (\InvalidArgumentException $e) {
    $errors = $e->findMessages(
        array(
            'email' => 'email error',
            'passw' => 'password error',
        )
    );
}

have you tried this ?

@alganet

This comment has been minimized.

Show comment Hide comment
@alganet

alganet Dec 4, 2012

Owner

I can confirm this is working:

            v::key('username', v::length(1,3))
                     ->key('birthdate', v::date())
                     ->setName("User Subscription Form")
                     ->assert(array('username' => 'xxxxx', 'birthdate' => 'x'));

The message output with the appropriate array keys is is this:

\-These rules must pass for User Subscription Form
  |-Key username must be valid
  | \-These rules must pass for "xxxxx"
  |   \-"xxxxx" must have a length between 1 and 3
  \-Key birthdate must be valid
    \-These rules must pass for "x"
      \-"x" must be a valid date

I'm already fixed it to this:

-These rules must pass for User Subscription Form
  |-Key username must be valid
  | \-"xxxxx" must have a length between 1 and 3
  \-Key birthdate must be valid
    \-"x" must be a valid date

This fix will be pushed today as soon as I exaustively test it!

Owner

alganet commented Dec 4, 2012

I can confirm this is working:

            v::key('username', v::length(1,3))
                     ->key('birthdate', v::date())
                     ->setName("User Subscription Form")
                     ->assert(array('username' => 'xxxxx', 'birthdate' => 'x'));

The message output with the appropriate array keys is is this:

\-These rules must pass for User Subscription Form
  |-Key username must be valid
  | \-These rules must pass for "xxxxx"
  |   \-"xxxxx" must have a length between 1 and 3
  \-Key birthdate must be valid
    \-These rules must pass for "x"
      \-"x" must be a valid date

I'm already fixed it to this:

-These rules must pass for User Subscription Form
  |-Key username must be valid
  | \-"xxxxx" must have a length between 1 and 3
  \-Key birthdate must be valid
    \-"x" must be a valid date

This fix will be pushed today as soon as I exaustively test it!

@alganet

This comment has been minimized.

Show comment Hide comment
@alganet

alganet Dec 4, 2012

Owner

This Push should fix the messages to display like the latest in the comment above! There is even a test there with that code. We'll release this in a package soon, but feel free to test the develop branch and tell if it worked!

Owner

alganet commented Dec 4, 2012

This Push should fix the messages to display like the latest in the comment above! There is even a test there with that code. We'll release this in a package soon, but feel free to test the develop branch and tell if it worked!

@nickl-

This comment has been minimized.

Show comment Hide comment
@nickl-

nickl- Dec 6, 2012

Member

Yeah!
Cheering panda

Member

nickl- commented Dec 6, 2012

Yeah!
Cheering panda

@Sequoia

This comment has been minimized.

Show comment Hide comment
@Sequoia

Sequoia Dec 19, 2012

+1 on "this is a big problem"; IMO this should be patched on packagist as soon as possible. I installed from there and this confusing issue cost a lot of time. The confusing nature of the docs exacerbated this issue.

To summarize, in my experience, there is no way to get an error message for $username = '***' to say "username must be alphanumeric", not using any combination of setName, getFullMessage, findMessages, var_dumping the error, or any other way. (I emphasize this only to make clear that this is not a usage issue.) The inability to return meaningful error messages severely limits the usefulness of a data validation library.

Sequoia commented Dec 19, 2012

+1 on "this is a big problem"; IMO this should be patched on packagist as soon as possible. I installed from there and this confusing issue cost a lot of time. The confusing nature of the docs exacerbated this issue.

To summarize, in my experience, there is no way to get an error message for $username = '***' to say "username must be alphanumeric", not using any combination of setName, getFullMessage, findMessages, var_dumping the error, or any other way. (I emphasize this only to make clear that this is not a usage issue.) The inability to return meaningful error messages severely limits the usefulness of a data validation library.

@alganet

This comment has been minimized.

Show comment Hide comment
@alganet

alganet Dec 20, 2012

Owner

Hey @Sequoia have you tried with the dev-develop package on Packagist? This version should have the fixes I mentioned some comments above. If that works fine for you, I'll create a minor release with the fixes =D

Owner

alganet commented Dec 20, 2012

Hey @Sequoia have you tried with the dev-develop package on Packagist? This version should have the fixes I mentioned some comments above. If that works fine for you, I'll create a minor release with the fixes =D

@silentworks

This comment has been minimized.

Show comment Hide comment
@silentworks

silentworks Jan 7, 2013

Hi @alganet I think you guys are missing out on what the message should read like, but even with current fix it is still wrong. Since the message returned is a string it doesn't make it any better.

The message should look like this:

-These rules must pass for User Subscription Form
  |-Key username must be valid
  | \-username must have a length between 1 and 3
  \-Key birthdate must be valid
    \-birthdate must be a valid date

Otherwise if the user enters nothing at all with the current code the message will read.

-These rules must pass for User Subscription Form
  |-Key username must be valid
  | \-"" must have a length between 1 and 3
  \-Key birthdate must be valid
    \-"" must be a valid date

No one know what "" must be a valid date is. Which field is it talking about? to better illustrate this if we were to use the findMessages() function instead the message looks like this:

array (size=1)
  'length' => string '"" must have a length between 4 and 22' (length=38)

This leads to confusion for the user of the website. There is no clue to what "" is, I hope this is more clear in order to reach a proper fix.

Hi @alganet I think you guys are missing out on what the message should read like, but even with current fix it is still wrong. Since the message returned is a string it doesn't make it any better.

The message should look like this:

-These rules must pass for User Subscription Form
  |-Key username must be valid
  | \-username must have a length between 1 and 3
  \-Key birthdate must be valid
    \-birthdate must be a valid date

Otherwise if the user enters nothing at all with the current code the message will read.

-These rules must pass for User Subscription Form
  |-Key username must be valid
  | \-"" must have a length between 1 and 3
  \-Key birthdate must be valid
    \-"" must be a valid date

No one know what "" must be a valid date is. Which field is it talking about? to better illustrate this if we were to use the findMessages() function instead the message looks like this:

array (size=1)
  'length' => string '"" must have a length between 4 and 22' (length=38)

This leads to confusion for the user of the website. There is no clue to what "" is, I hope this is more clear in order to reach a proper fix.

@alganet

This comment has been minimized.

Show comment Hide comment
@alganet

alganet Mar 29, 2013

Owner

I finally got it and I'm really sorry for not understanding this before.

Maybe you can run it working today. I need to test, unit test and document this if it works.

Try {{reference}} on the template message override. The Respect\Validation\Validator class exposes all public members of the validator as template variables (using get_object_vars). {{name}} is overriden a couple of times 'cause it's dynamic. $reference is a public member of AbstractRelated, the parent of Key, Attribute and a couple of validators, so it should be available for key.

If this doesn't work, this is the intended behavior and I will make sure it works =)

Owner

alganet commented Mar 29, 2013

I finally got it and I'm really sorry for not understanding this before.

Maybe you can run it working today. I need to test, unit test and document this if it works.

Try {{reference}} on the template message override. The Respect\Validation\Validator class exposes all public members of the validator as template variables (using get_object_vars). {{name}} is overriden a couple of times 'cause it's dynamic. $reference is a public member of AbstractRelated, the parent of Key, Attribute and a couple of validators, so it should be available for key.

If this doesn't work, this is the intended behavior and I will make sure it works =)

@mrahmadt

This comment has been minimized.

Show comment Hide comment
@mrahmadt

mrahmadt May 20, 2013

{{reference}} not working

Array ( [alnum] => [length] => {{reference}} must not have more than 15 chars [noWhitespace] => )

to be frank with you, this is very strange bug/limitation that can prevent many people from using it because it's just confusing users

{{reference}} not working

Array ( [alnum] => [length] => {{reference}} must not have more than 15 chars [noWhitespace] => )

to be frank with you, this is very strange bug/limitation that can prevent many people from using it because it's just confusing users

@nivek005

This comment has been minimized.

Show comment Hide comment
@nivek005

nivek005 May 30, 2013

I agree. This library is awesome and has everything you'd need for validation except the most important part, being able to easily output a list of readable errors. Without that functionality most people aren't going to be able to use it. Outputting errors by field names should be the default and outputting by field value should be optional. Otherwise you wind up having to write something like this which defeats the whole purpose of the library:

$errors = array();
if (!v::notEmpty()->validate($_POST['name'])) $errors[] = 'Name is required.';
if (!v::alpha()->validate($_POST['name'])) $errors[] = 'Name must be letters only.';
if (!v::length(0,200)->validate($_POST['name'])) $errors[] = 'Name must be less than 200 characters.';
if(!empty($errors)) { ... }

I agree. This library is awesome and has everything you'd need for validation except the most important part, being able to easily output a list of readable errors. Without that functionality most people aren't going to be able to use it. Outputting errors by field names should be the default and outputting by field value should be optional. Otherwise you wind up having to write something like this which defeats the whole purpose of the library:

$errors = array();
if (!v::notEmpty()->validate($_POST['name'])) $errors[] = 'Name is required.';
if (!v::alpha()->validate($_POST['name'])) $errors[] = 'Name must be letters only.';
if (!v::length(0,200)->validate($_POST['name'])) $errors[] = 'Name must be less than 200 characters.';
if(!empty($errors)) { ... }
@alganet

This comment has been minimized.

Show comment Hide comment
@alganet

alganet Jun 9, 2013

Owner

Hi @nivek005 an @mrahmadt! I've published a complete sample of Respect\Validation applied to an HTML form using error messages (including custom ones). It's published here: https://github.com/Respect/samples/tree/master/public/form-validation. The sample does not fix {{reference}}, but uses another set of more stable APIs to achieve a similar result.

The reporting mechanism is indeed limited to work rule-centric, not attribute-centric. In order to overcome this there are two different special rules (for grouped rules and for sub-data validation like attributes and keys). I'm working to make their APIs more stable. Based on the sample, do you have any suggestions?

Owner

alganet commented Jun 9, 2013

Hi @nivek005 an @mrahmadt! I've published a complete sample of Respect\Validation applied to an HTML form using error messages (including custom ones). It's published here: https://github.com/Respect/samples/tree/master/public/form-validation. The sample does not fix {{reference}}, but uses another set of more stable APIs to achieve a similar result.

The reporting mechanism is indeed limited to work rule-centric, not attribute-centric. In order to overcome this there are two different special rules (for grouped rules and for sub-data validation like attributes and keys). I'm working to make their APIs more stable. Based on the sample, do you have any suggestions?

@nickl-

This comment has been minimized.

Show comment Hide comment
@nickl-

nickl- Sep 23, 2013

Member

Considered resolved no activity for 4 months.

Member

nickl- commented Sep 23, 2013

Considered resolved no activity for 4 months.

@nickl- nickl- closed this Sep 23, 2013

@silentworks

This comment has been minimized.

Show comment Hide comment
@silentworks

silentworks Oct 9, 2013

@lexx27 I went with https://github.com/vlucas/valitron It had all the features I needed and the ones it didn't I sent in a PR and fixed it.

@lexx27 I went with https://github.com/vlucas/valitron It had all the features I needed and the ones it didn't I sent in a PR and fixed it.

@lexx27

This comment has been minimized.

Show comment Hide comment
@lexx27

lexx27 Oct 9, 2013

Thanks a lot @silentworks ! Valitron was the one I was looking at too. It looks good. I also found https://github.com/Wixel/GUMP but it doesnt support composer yet, and I am too bored to manage libs outside composer

lexx27 commented Oct 9, 2013

Thanks a lot @silentworks ! Valitron was the one I was looking at too. It looks good. I also found https://github.com/Wixel/GUMP but it doesnt support composer yet, and I am too bored to manage libs outside composer

@nickl-

This comment has been minimized.

Show comment Hide comment
@nickl-

nickl- Oct 10, 2013

Member

Reopened due to vested interest.

@lexx27 and @silentworks please provide a list of actionable tasks which if done, you will agree this issue is finally resolved.

Thank you for your time and consideration.

Member

nickl- commented Oct 10, 2013

Reopened due to vested interest.

@lexx27 and @silentworks please provide a list of actionable tasks which if done, you will agree this issue is finally resolved.

Thank you for your time and consideration.

@nickl- nickl- reopened this Oct 10, 2013

@lexx27

This comment has been minimized.

Show comment Hide comment
@lexx27

lexx27 Oct 10, 2013

Hello @nickl-

When I write something like

$input = 'ab';
val::length(5,300)->setName(' a whatever Name')->check($input);

Then, when I catch the exception error I should get a meaningful validation error. Which I get...
But it should also include the name I just entered via the setName method.

Instead of

"ab" must have a length between 5 and 300

I should get

a whatever Name must have a length between 5 and 300

Yesterday I tried to understand where is the bug in your implementation.
The setName method assigns correctly the name to the object.
But later somehow "$this->name" becomes null again.
I could not find where it became null and I stopped searching.

Thats all for now

lexx27 commented Oct 10, 2013

Hello @nickl-

When I write something like

$input = 'ab';
val::length(5,300)->setName(' a whatever Name')->check($input);

Then, when I catch the exception error I should get a meaningful validation error. Which I get...
But it should also include the name I just entered via the setName method.

Instead of

"ab" must have a length between 5 and 300

I should get

a whatever Name must have a length between 5 and 300

Yesterday I tried to understand where is the bug in your implementation.
The setName method assigns correctly the name to the object.
But later somehow "$this->name" becomes null again.
I could not find where it became null and I stopped searching.

Thats all for now

@jimbocoder

This comment has been minimized.

Show comment Hide comment
@jimbocoder

jimbocoder Oct 10, 2013

My company is also pretty much hinging adoption of Respect\Validation on this feature. We wish to take it a step further and produce some API documentation based on the configured validators.

My company is also pretty much hinging adoption of Respect\Validation on this feature. We wish to take it a step further and produce some API documentation based on the configured validators.

@alganet

This comment has been minimized.

Show comment Hide comment
@alganet

alganet Oct 10, 2013

Owner

Sorry for being absent in the last few months. I've found the problem and I would like suggestions to fix it!

First, let's consider the object structure generated from a chain. I'm gonna use this previously mentioned sample:

$input = 'ab';
val::length(5,300)->setName(' a whatever Name')->check($input);

The chain above is equivalent to the following object configuration

$input = 'ab';
$lengthValidator = new \Respect\Validation\Rules\Length(5, 300);
$validator = new Respect\Validation\Validator($lengthValidator);
$validator->setName(' a whatever Name');
$validator->check($input);

This already gives us a hint. The Respect\Validation\Validator extends the AllOf rule which is used to build the chain. When you set the name on the chain you're setting the name on the AllOf (the validator that groups all other chain calls) and not the Length instance (which is a node from the AllOf). Both validators and messages are built as composites.

As rules are standalone, a simple solution for that would be:

$input = 'ab';
$validator= new \Respect\Validation\Rules\Length(5, 300);
$validator->setName(' a whatever Name');
$validator->check($input);

The code above produces "a whatever Name must have a length between 5 and 300", which is correct.

So, "setName" is working, but its composite meaning (what it does in a composite validator) isn't usable. I'm thinking of adding a new "named" method that always work on the last node of the chain:

$input = 'ab';
val::length(5,300)->named(' a whatever Name')
    ->alnum()->named("something else just for alnum")
    ->check($input);

A "named" working implementation on the AbstractComposite should be similar to this (tested informally and OK over here):

    public function named($name)
    {
        end($this->rules)->setName($name);
        return $this;
    }

We still need the old setName in order to name grouped validators, so changing it is not an option.

I'm interested in all feedback possible. Thank you!

Owner

alganet commented Oct 10, 2013

Sorry for being absent in the last few months. I've found the problem and I would like suggestions to fix it!

First, let's consider the object structure generated from a chain. I'm gonna use this previously mentioned sample:

$input = 'ab';
val::length(5,300)->setName(' a whatever Name')->check($input);

The chain above is equivalent to the following object configuration

$input = 'ab';
$lengthValidator = new \Respect\Validation\Rules\Length(5, 300);
$validator = new Respect\Validation\Validator($lengthValidator);
$validator->setName(' a whatever Name');
$validator->check($input);

This already gives us a hint. The Respect\Validation\Validator extends the AllOf rule which is used to build the chain. When you set the name on the chain you're setting the name on the AllOf (the validator that groups all other chain calls) and not the Length instance (which is a node from the AllOf). Both validators and messages are built as composites.

As rules are standalone, a simple solution for that would be:

$input = 'ab';
$validator= new \Respect\Validation\Rules\Length(5, 300);
$validator->setName(' a whatever Name');
$validator->check($input);

The code above produces "a whatever Name must have a length between 5 and 300", which is correct.

So, "setName" is working, but its composite meaning (what it does in a composite validator) isn't usable. I'm thinking of adding a new "named" method that always work on the last node of the chain:

$input = 'ab';
val::length(5,300)->named(' a whatever Name')
    ->alnum()->named("something else just for alnum")
    ->check($input);

A "named" working implementation on the AbstractComposite should be similar to this (tested informally and OK over here):

    public function named($name)
    {
        end($this->rules)->setName($name);
        return $this;
    }

We still need the old setName in order to name grouped validators, so changing it is not an option.

I'm interested in all feedback possible. Thank you!

@lexx27

This comment has been minimized.

Show comment Hide comment
@lexx27

lexx27 Oct 10, 2013

Now I get it :)

Interesting workaround. Will your solution require to set a name for each validator?

For me the most usable case is to just add one name for all the validators once.
Do you think adding(optionally) the name as a second argument on the check method is an option?

like:

$input = 'ab';
val::length(5,300)
    ->alnum()
    ->check($input, "my input name");

lexx27 commented Oct 10, 2013

Now I get it :)

Interesting workaround. Will your solution require to set a name for each validator?

For me the most usable case is to just add one name for all the validators once.
Do you think adding(optionally) the name as a second argument on the check method is an option?

like:

$input = 'ab';
val::length(5,300)
    ->alnum()
    ->check($input, "my input name");
@lexx27

This comment has been minimized.

Show comment Hide comment
@lexx27

lexx27 Nov 1, 2013

Is there anybody on that? Should I give it a try fixing it?

lexx27 commented Nov 1, 2013

Is there anybody on that? Should I give it a try fixing it?

@silentworks

This comment has been minimized.

Show comment Hide comment
@silentworks

silentworks Nov 2, 2013

its good to see this getting looked at, I agree that I would want to set 1 name for all validators than 1 per validator.

its good to see this getting looked at, I agree that I would want to set 1 name for all validators than 1 per validator.

@CMCDragonkai

This comment has been minimized.

Show comment Hide comment
@CMCDragonkai

CMCDragonkai Nov 7, 2013

What about when one calls allOf?

Something like this:

v::allOf(
    v::key(
        'url', 
        v::call(
            'parse_url', 
            v:arr()
            ->key('scheme', v::notEmpty()),
            ->key('host', v::domain())
        )
    )->setName('Url (url)'), 
    v::key('width', v::int()->between(200, 4000, true), false)->setName('Width (width)'), 
    v::key('height', v::int()->between(200, 4000, true), false)->setName('Height (height)'), 
    v::key(
        'imgformat', 
        v::string()->oneOf(
            v::equals('png'),
            v::equals('jpg'),
            v::equals('jpeg')
        ), 
        false
    )->setName('Image format (imgformat)')
)->assert($parameters);

In asserting the $parameters. I am expecting error messages to unfold like this or something that has the same information. How would I achieve that using findMessages()?

[
    'Url (url)' => 'First validation error',
    'Width (width)' => 'First width validation error',
    'Height (height)' => 'First height validation error',
    'Image format (imgformat)' => 'First image format error',
]

What about when one calls allOf?

Something like this:

v::allOf(
    v::key(
        'url', 
        v::call(
            'parse_url', 
            v:arr()
            ->key('scheme', v::notEmpty()),
            ->key('host', v::domain())
        )
    )->setName('Url (url)'), 
    v::key('width', v::int()->between(200, 4000, true), false)->setName('Width (width)'), 
    v::key('height', v::int()->between(200, 4000, true), false)->setName('Height (height)'), 
    v::key(
        'imgformat', 
        v::string()->oneOf(
            v::equals('png'),
            v::equals('jpg'),
            v::equals('jpeg')
        ), 
        false
    )->setName('Image format (imgformat)')
)->assert($parameters);

In asserting the $parameters. I am expecting error messages to unfold like this or something that has the same information. How would I achieve that using findMessages()?

[
    'Url (url)' => 'First validation error',
    'Width (width)' => 'First width validation error',
    'Height (height)' => 'First height validation error',
    'Image format (imgformat)' => 'First image format error',
]
@nickl-

This comment has been minimized.

Show comment Hide comment
@nickl-

nickl- Nov 28, 2013

Member

Great work guys! Anyone keen to roll a PR for review already?

Member

nickl- commented Nov 28, 2013

Great work guys! Anyone keen to roll a PR for review already?

@nickl-

This comment has been minimized.

Show comment Hide comment
@nickl-

nickl- Jan 1, 2014

Member

@lexx27 Still want to attempt a fix for this?

Member

nickl- commented Jan 1, 2014

@lexx27 Still want to attempt a fix for this?

@augustohp augustohp modified the milestones: 0.7.0, 0.6.1 Feb 17, 2014

@augustohp augustohp modified the milestones: Backlog, 0.7.0 May 9, 2014

SBhojani added a commit to SBhojani/Validation that referenced this issue Jun 4, 2014

A qucik fix for Respect#86
Fixing the issue discussed in Respect#86 so atleast the following code gives the field names in the error messages:

    try{
        v::string()->setName('First Name')->notEmpty()->noWhitespace()->alpha()->assert($_POST['txt_first_name']);
    }catch (\Respect\Validation\Exceptions\ValidationException $e){
        echo $e->getFullMessage();
    }
@FoxxMD

This comment has been minimized.

Show comment Hide comment
@FoxxMD

FoxxMD Apr 21, 2015

👍

FoxxMD commented Apr 21, 2015

👍

@asperon

This comment has been minimized.

Show comment Hide comment
@asperon

asperon Jun 30, 2015

Anybody looking into this?

asperon commented Jun 30, 2015

Anybody looking into this?

@henriquemoody

This comment has been minimized.

Show comment Hide comment
@henriquemoody

henriquemoody Jun 30, 2015

Owner

Looks like we still haven't changed it yet, even with the Key rule.

This code:

try {
    v::key('username', v::alnum()->noWhitespace()->length(4,22))->check($_POST);
} catch (ValidationExceptionInterface $exception) {
    echo $exception->getMainMessage().PHP_EOL;
}

Displays this message:

"a b" must not contain whitespace

But what you was expecting was:

"username" must not contain whitespace

I'm not sure if we can even fix this on the current version because even if it's not the expected behaviour by many of you I don't see this as a Bug, it's just a different behaviour and there are test counting with this behaviour.

However, this is going to change on our first major version, as you can see on this test: simple-full-message-with-key-4. So, you may consider this as covered.

Owner

henriquemoody commented Jun 30, 2015

Looks like we still haven't changed it yet, even with the Key rule.

This code:

try {
    v::key('username', v::alnum()->noWhitespace()->length(4,22))->check($_POST);
} catch (ValidationExceptionInterface $exception) {
    echo $exception->getMainMessage().PHP_EOL;
}

Displays this message:

"a b" must not contain whitespace

But what you was expecting was:

"username" must not contain whitespace

I'm not sure if we can even fix this on the current version because even if it's not the expected behaviour by many of you I don't see this as a Bug, it's just a different behaviour and there are test counting with this behaviour.

However, this is going to change on our first major version, as you can see on this test: simple-full-message-with-key-4. So, you may consider this as covered.

@henriquemoody henriquemoody removed the Bug label Jun 30, 2015

@henriquemoody henriquemoody modified the milestones: 1.0, Backlog Jun 30, 2015

@henriquemoody

This comment has been minimized.

Show comment Hide comment
@henriquemoody

henriquemoody Jun 30, 2015

Owner

Any way, this looks easy to change, see #365.

I'm just not sure if we should release this on 0.9<, 0.10 or just on 1.0. Any thoughts?

Owner

henriquemoody commented Jun 30, 2015

Any way, this looks easy to change, see #365.

I'm just not sure if we should release this on 0.9<, 0.10 or just on 1.0. Any thoughts?

@henriquemoody henriquemoody removed this from the 1.0 milestone Jun 30, 2015

@henriquemoody henriquemoody added this to the 0.10 milestone Jul 16, 2015

@augustohp

This comment has been minimized.

Show comment Hide comment
@augustohp

augustohp Jul 16, 2015

Owner

I'm just not sure if we should release this on 0.9<, 0.10 or just on 1.0. Any thoughts?

0.10, I would not change this on 0.9 which is the current version, right?

Owner

augustohp commented Jul 16, 2015

I'm just not sure if we should release this on 0.9<, 0.10 or just on 1.0. Any thoughts?

0.10, I would not change this on 0.9 which is the current version, right?

@henriquemoody

This comment has been minimized.

Show comment Hide comment
@henriquemoody

henriquemoody Jul 17, 2015

Owner

Yeah, I just kept it on master only.

Owner

henriquemoody commented Jul 17, 2015

Yeah, I just kept it on master only.

@henriquemoody henriquemoody removed this from the 1.0 milestone Aug 9, 2015

@chozilla

This comment has been minimized.

Show comment Hide comment
@chozilla

chozilla Jul 26, 2016

Hello, as fare as I can tell, the described problem is not fixed.
The ->setName() function still does not behave as expected or described in the use cases in this discussion.

// example
$testValue = array();
$testValue['nameFirst'] = 'Jane DOOO0E FILLTEXT! MUCH LONG';
$testValue['nameLast'] = 'Doe';

$nameValidator = \Respect\Validation\Validator::stringType()->setName('First Name')
  ->alpha()->setName('First Name')
  ->noWhitespace()->setName('First Name')
  ->length(2, 15)->setName('First Name');

try {
    \Respect\Validation\Validator::key('nameFirst', $nameValidator)->setName('First Name')->assert($testValue);
} catch(\Respect\Validation\Exceptions\NestedValidationException $nestedException) {

  $nestedException->setName('First Name');

  foreach($nestedException as $exception) {
    $exception->setName('First Name');
  }
  print_r($nestedException->getMessages())
}

Outputs:

Array ( 
  [0] => These rules must pass for nameFirst 
  [1] => nameFirst must contain only letters (a-z) 
  [2] => nameFirst must not contain whitespace 
  [3] => nameFirst must have a length between 2 and 15 
) 

Whatever I try... I am not able to replace 'nameFirst' with 'First Name' with any means provided by the basic Validator API.

EDIT
Ok, I found one way to make the message display correctly, but this is for sure not what was intended.

try {
    \Respect\Validation\Validator::key('nameFirst', $nameValidator)->assert($testValue);
} catch(\Respect\Validation\Exceptions\NestedValidationException $nestedException) {

  foreach($nestedException as $exception) {
    //If you set the name on the child exceptions...
    $exception->setName('First Name'); 
    //...and trigger the setting of the 'name' param...
    $exception->setParam('name', 'WHATEVER'); 
    //...you get the expected output. (it does not matter what value you set)
  }
  print_r($nestedException->getMessages())
}

Outputs:

Array (
  [0] => These rules must pass for First Name 
  [1] => First Name must contain only letters (a-z) 
  [2] => First Name must not contain whitespace 
  [3] => First Name must have a length between 2 and 15 
) 

chozilla commented Jul 26, 2016

Hello, as fare as I can tell, the described problem is not fixed.
The ->setName() function still does not behave as expected or described in the use cases in this discussion.

// example
$testValue = array();
$testValue['nameFirst'] = 'Jane DOOO0E FILLTEXT! MUCH LONG';
$testValue['nameLast'] = 'Doe';

$nameValidator = \Respect\Validation\Validator::stringType()->setName('First Name')
  ->alpha()->setName('First Name')
  ->noWhitespace()->setName('First Name')
  ->length(2, 15)->setName('First Name');

try {
    \Respect\Validation\Validator::key('nameFirst', $nameValidator)->setName('First Name')->assert($testValue);
} catch(\Respect\Validation\Exceptions\NestedValidationException $nestedException) {

  $nestedException->setName('First Name');

  foreach($nestedException as $exception) {
    $exception->setName('First Name');
  }
  print_r($nestedException->getMessages())
}

Outputs:

Array ( 
  [0] => These rules must pass for nameFirst 
  [1] => nameFirst must contain only letters (a-z) 
  [2] => nameFirst must not contain whitespace 
  [3] => nameFirst must have a length between 2 and 15 
) 

Whatever I try... I am not able to replace 'nameFirst' with 'First Name' with any means provided by the basic Validator API.

EDIT
Ok, I found one way to make the message display correctly, but this is for sure not what was intended.

try {
    \Respect\Validation\Validator::key('nameFirst', $nameValidator)->assert($testValue);
} catch(\Respect\Validation\Exceptions\NestedValidationException $nestedException) {

  foreach($nestedException as $exception) {
    //If you set the name on the child exceptions...
    $exception->setName('First Name'); 
    //...and trigger the setting of the 'name' param...
    $exception->setParam('name', 'WHATEVER'); 
    //...you get the expected output. (it does not matter what value you set)
  }
  print_r($nestedException->getMessages())
}

Outputs:

Array (
  [0] => These rules must pass for First Name 
  [1] => First Name must contain only letters (a-z) 
  [2] => First Name must not contain whitespace 
  [3] => First Name must have a length between 2 and 15 
) 
@FoxxMD

This comment has been minimized.

Show comment Hide comment
@FoxxMD

FoxxMD Jul 27, 2016

For anyone else coming across this who wants to use Respect with models and also like to have this sensible default (getting error messages with attribute name rather than value)

abstract class Base {
    protected abstract function getValidationRules();

    //http://respect.li/Validation/docs/validators.html
    public function validate($rules = null, $catchAndReturn = false) {

        $errors = [];
        $rulesToRun = null === $rules ? $this->getValidationRules() : $rules;
        foreach ($rulesToRun as $validator) {
            try {
                $validator->check($this);
            } catch (ExceptionInterface $e) {
                $varName = current($validator->getRules())->getName();
                $errors[$varName] = $e->getMainMessage();
            }
        }
        if ($catchAndReturn) {
            return $errors;
        } else {
            if (!empty($errors)) {
                throw new ValidationFailureException('Validation failed for this object.', $errors);
            }
        }
    }
}

and then in your model:

    protected function getValidationRules()
    {
        return [
            v::attribute('name', v::notEmpty()),
            v::attribute('type', v::notEmpty()),
            v::attribute('userId', v::numeric()),
            v::attribute('createDate', v::notEmpty()->date())
        ];
    }

FoxxMD commented Jul 27, 2016

For anyone else coming across this who wants to use Respect with models and also like to have this sensible default (getting error messages with attribute name rather than value)

abstract class Base {
    protected abstract function getValidationRules();

    //http://respect.li/Validation/docs/validators.html
    public function validate($rules = null, $catchAndReturn = false) {

        $errors = [];
        $rulesToRun = null === $rules ? $this->getValidationRules() : $rules;
        foreach ($rulesToRun as $validator) {
            try {
                $validator->check($this);
            } catch (ExceptionInterface $e) {
                $varName = current($validator->getRules())->getName();
                $errors[$varName] = $e->getMainMessage();
            }
        }
        if ($catchAndReturn) {
            return $errors;
        } else {
            if (!empty($errors)) {
                throw new ValidationFailureException('Validation failed for this object.', $errors);
            }
        }
    }
}

and then in your model:

    protected function getValidationRules()
    {
        return [
            v::attribute('name', v::notEmpty()),
            v::attribute('type', v::notEmpty()),
            v::attribute('userId', v::numeric()),
            v::attribute('createDate', v::notEmpty()->date())
        ];
    }
@JCMais

This comment has been minimized.

Show comment Hide comment
@JCMais

JCMais Nov 28, 2016

After some tries, for people having issues while trying to validate keys, make sure you are calling setName to the validators for the key:

v::key( 'pass', v::stringType()->length( 6 )->setName( 'Password' ) )

# Password must have a length greater than 6
v::key( 'pass', v::stringType()->length( 6 ) )->setName( 'Password' )

# pass must have a length greater than 6

JCMais commented Nov 28, 2016

After some tries, for people having issues while trying to validate keys, make sure you are calling setName to the validators for the key:

v::key( 'pass', v::stringType()->length( 6 )->setName( 'Password' ) )

# Password must have a length greater than 6
v::key( 'pass', v::stringType()->length( 6 ) )->setName( 'Password' )

# pass must have a length greater than 6
@chozilla

This comment has been minimized.

Show comment Hide comment
@chozilla

chozilla Jan 25, 2017

I thought my example where i call setName() in like 7 different places showed that this is not the case...

I thought my example where i call setName() in like 7 different places showed that this is not the case...

@JCMais

This comment has been minimized.

Show comment Hide comment
@JCMais

JCMais Jan 26, 2017

@chozilla you probably are using an outdated version. Because I get the correct output with the code I posted.

JCMais commented Jan 26, 2017

@chozilla you probably are using an outdated version. Because I get the correct output with the code I posted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment