CodeIgniter4 icon indicating copy to clipboard operation
CodeIgniter4 copied to clipboard

Bug: Print errors in array validations

Open luispastendev opened this issue 5 years ago • 10 comments

Hello I am trying to print the errors when I validate an array structure for example:

<select multiple name="categories[]">
# validation rules
 'categories.*' => 'is_not_unique[categories.id]'

# return errors
return redirect()->back()
                ->with('errors', $this->validator->getErrors())

then I try to print the errors in my html but it cannot show them, I suppose it is because of the key format that the function to obtain the errors returns

<?=session('errors.categories.*')?>

I think it is not the most practical way to return errors when it comes to array validations :(

thanks for everything!

luispastendev avatar Nov 23 '20 16:11 luispastendev

If you use <?= print_r(session('errors.categories'), true) ?> will there be outputs?

paulbalandan avatar Jan 06 '21 08:01 paulbalandan

Hello Paul!

try to print it that way but a null value is returned, the format of the array returned in session is as follows

array (5) {
//    ...
     ["categories.*"] =>
   string (80) "The categories.* field must contain a previously existing value in the database."
}

It would be quite nice if the ". *" Could be omitted in the name of the keys when dealing with array validations, or how could I get the error message?

Cheers!

luispastendev avatar Jan 07 '21 04:01 luispastendev

Try setting a label to your validation rules:

// validation rules
'categories.*' => ['rules' => 'is_not_unique[categories.id]', 'label' => 'categories'],
// The categories field ...

But note that the array key will still be categories.* since this is the field name passed to the errors array.

paulbalandan avatar Jan 07 '21 13:01 paulbalandan

It seems that the name of the label is not associated with the name of the error key because I have tried to put a label to the configuration and it keeps returning categories.*

'categories.*' => [
    'rules' => 'is_not_unique[categories.id]',
    'label' => 'categories',
],

imagen

as I mentioned before if I try to print the error as = session ('errors.categories. *')?> it returns null

luispastendev avatar Jan 07 '21 16:01 luispastendev

It seems like a bug related to fact that we're using dot syntax to handle the nested array values.

Until we solve this I guess you should be able to use something like this:

<?= session('errors')['categories.*'] ?>

michalsn avatar Jan 07 '21 17:01 michalsn

But note that the array key will still be categories.* since this is the field name passed to the errors array.

It seems that the name of the label is not associated with the name of the error key because I have tried to put a label to the configuration and it keeps returning categories.*

'categories.*' => [
    'rules' => 'is_not_unique[categories.id]',
    'label' => 'categories',
],

imagen

as I mentioned before if I try to print the error as it returns null

Yes, as I've said earlier, the field name will still be used as the array key.

This is because of the following line in Validation::processRules. https://github.com/codeigniter4/CodeIgniter4/blob/e2e5ecabf25b7c64fe6f0f3e2dcfe3f367ee507f/system/Validation/Validation.php#L326

The $field is used as the index for storing the error messages in the $this->errors array. @michalsn The simple fix I see is using rtrim on $field before being used as index, like $this->errors[rtrim('$field', '.*')] = .. but I'm not sure if this will not cause a confusion because categories, or any other multiple-value fields, will look like a single-value field much like the other fields.

paulbalandan avatar Jan 07 '21 17:01 paulbalandan

@paulbalandan Yes, this might be confusing and a little too "magical". Also it would introduce a breaking compatibility, since this bug is valid only if we want to display errors via session.

I was thinking more about adding some new (optional) value to validation array, like:

'categories.*' => [
    'rules' => 'is_not_unique[categories.id]',
    'label' => 'Categories',
    'as' => 'categories',
],

With a note in the user guide that as should contain only alpha numeric value with dash or underscore. This way everything would be easier to understand. But these are just my initial thoughts.

There is a workaround for this bug, so it's nothing urgent, I think.

michalsn avatar Jan 07 '21 17:01 michalsn

It seems to be a good idea from michals, although it is not something urgent to solve since it can be solved with this <?= session('errors')['categories.*'] ?>, by the way, nice that you are here again @michalsn :)

luispastendev avatar Jan 07 '21 18:01 luispastendev

Since v4.2 getErrors() returns like this: https://github.com/codeigniter4/CodeIgniter4/blob/6b077b7953f1ac4c34d38cd154ce23dce43f2f51/tests/system/Validation/ValidationTest.php#L873-L879 Ref #5609

So it seems session('errors')['categories.*'] does not work.

$validation->getError('categories.*') returns all found errors that will be combined into one line separated by the EOL character: https://github.com/codeigniter4/CodeIgniter4/blob/6b077b7953f1ac4c34d38cd154ce23dce43f2f51/tests/system/Validation/ValidationTest.php#L881-L885

kenjis avatar Jul 08 '22 03:07 kenjis

session('errors.categories.*') searches an item with dot notation, and there is no such key in the array. Because the array key is categories.* (at the time the bug was reported), and dot_array_search() does not find such a key. So it returns null.

So this does not seem a bug.

kenjis avatar Jul 08 '22 05:07 kenjis