Respect / Validation

The most awesome validation engine ever created for PHP
https://respect-validation.readthedocs.io
MIT License
5.76k stars 774 forks source link

Inconsistent Exception messages #1376

Closed nipunadodan closed 1 year ago

nipunadodan commented 2 years ago

It's an awesome library to leave for this hard to get right Exception handling and painful documentations. I've got getFullMessage() returned as expected but it's just as a String. $e->getMessages() only outputs one error message from one key/attribute, which shouldn't be the case.

$postValidator = Valid::attribute('title',Valid::length(2,3)->stringType())
            ->attribute('description',Valid::stringType())
            ->attribute('author',Valid::intType()->length(1,2))
            ->attribute('user',Valid::intVal()->length(1,2));
try {
    $postValidator->assert($input);
} catch (NestedValidationException $e) {
    echo json_encode($e->getMessages());
}

With $e->getMessages() _(after jsonencoded)

{
    "title": "title must be of type string",
    "author": "author must have a length between 1 and 2",
    "user": "Attribute user must be present"
}

With $e->getFullMessage()

 - All of the required rules must pass for title\n    
    - title must have a length between 2 and 3\n    
    - title must be of type string\n  
 - All of the required rules must pass for author\n    
    - author must be of type integer\n    
    - author must have a length between 1 and 2\n    
 - Attribute user must be present

The later has more information. Is there a way I can get all of the information shown with $e->getMessages()? Moreover, I think this is a bug. Isn't it?

alganet commented 1 year ago

We used to have a findMessages() method that was able to do so, but this started to become out of scope for us. We might bring back that feature in the future.

We might be able to expose $e->getRecursiveIterator(), that will give you a RecursiveIteratorIterator to play with that has all the nesting information you want. The problem is: that PHP interface is way too confusing.

I'm keeping this open, because it is something I believe we should have. I can't do it for the next release, but it should be on our radar soon.

alganet commented 1 year ago

I realized you can already do that using the RecursiveExceptionIterator we provide.

I added a test case for that scenario which shows how to get the message and level on the tree for each exception in detail:

https://github.com/Respect/Validation/blob/2.3/tests/integration/issue-1376.phpt

TL;DR


use Respect\Validation\Exceptions\NestedValidationException;
use Respect\Validation\Exceptions\RecursiveExceptionIterator;

try {
    $postValidator->assert($input);
} catch (NestedValidationException $e) {
    $explorer = new RecursiveIteratorIterator(
        new RecursiveExceptionIterator($e),
        RecursiveIteratorIterator::SELF_FIRST
    );
    foreach ($explorer as $innerException) {
        var_dump([
            'level' => $explorer->getDepth(),
            'message' => $innerException->getMessage(),
        ]);
    }
}

This can be useful if you don't want getMessages() to flatten the messages choosing which ones to display for you.

I'm closing this now, since apparently there are no needed changes.

Let me know if that works for you! If it doesn't, please feel free to reopen this.

nipunadodan commented 1 year ago

I will check this out and will let you know if it doesn't work. Thank you very much for this!!