yiisoft / validator

Yii validator library
https://www.yiiframework.com/
BSD 3-Clause "New" or "Revised" License
110 stars 36 forks source link

Validation error output #610

Closed bouledepate closed 1 year ago

bouledepate commented 1 year ago

Hi everyone again :)

My input data array contains dot-separated keys. According to the documentation, it is recommended to escape such keys so as not to break them into subcollections. This is good, but when I get the list of errors via getErrorMessagesIndexedByPath I don't want to see the escaping. I looked at the code and saw what can be done:

The 1st way is to move the parameter to a separate flag.

    public function getErrorMessagesIndexedByPath(string $separator = '.', bool $escape = true): array
    {
        $errors = [];
        foreach ($this->errors as $error) {
            $stringValuePath = implode($separator, $error->getValuePath($escape));
            $errors[$stringValuePath][] = $error->getMessage();
        }
        return $errors;
    }

2nd way - just remove it.

    public function getErrorMessagesIndexedByPath(string $separator = '.'): array
    {
        $errors = [];
        foreach ($this->errors as $error) {
            $stringValuePath = implode($separator, $error->getValuePath());
            $errors[$stringValuePath][] = $error->getMessage();
        }
        return $errors;
    }

Example. If the parameter is set to "true", then I get this output.

    "error": {
        "code": 790,
        "title": "Validation error!",
        "detail": {
            "filters.amount\\.value": [
                "Value must be a number."
            ]
        }
    }

Otherwise like this.

"error": {
        "code": 790,
        "title": "Validation error!",
        "detail": {
            "filters.amount.value": [
                "Value must be a number."
            ]
        }
    }

Do you agree that the second conclusion is much better and more convenient? Thank you!

What steps will reproduce the problem?

  1. Make validation of data with keys 'amount.value' for example.
  2. Request the error messages by 'getErrorMessagesIndexedByPath';

What is the expected result?

Paths without escaping.

What do you get instead?

Paths with escaping.

Additional info

Q A
Version 1.0.1
PHP version 8.2.6
Operating system Linux Ubuntu 20.04
arogachev commented 1 year ago

What is your use case for this method?

bouledepate commented 1 year ago

@arogachev,

I have REST API. After validating the data with this method, I get all the errors given their path, since I'm using a Nested validator. Then I generate an exception, where I put the received array of errors, encode it through json_encode and give it to the client. And as planned, the key in this array can look like: "account.profile.name".

Also, "account.profile.name" is the key in the array of data that comes from the client to the server and it sends them for validation. Therefore, in order to avoid the behavior that Nested validator has, when "sub-arrays" are formed from such keys, I follow the documentation and escape the dots. "account/.profile/.name".

If a key contains the separator (.), or Each shortcut (*), it must be escaped with backslash () in the rule config to work correctly. In the input data escaping is not needed.

If the "account.profile.name" attribute fails validation, then I would expect to see the following in the response from the getErrorMessagesIndexedByPath: {"account.profile.name": "error text"}, but not {"account//.profile//.name": "error text"}

bouledepate commented 1 year ago

I hope you got what I meant :)

samdark commented 1 year ago

Makes sense. Thanks for suggestion, @bouledepate

vjik commented 1 year ago

I prefer first way with additional parameter in Result::getAttributeErrorMessagesIndexedByPath() and Result::getErrorMessagesIndexedByPath() and by default escape separator chars in value path elements. It's allow to consumers correctly parse result keys.