laminas / laminas-form

Validate and display simple and complex forms, casting forms to business objects and vice versa
https://docs.laminas.dev/laminas-form/
BSD 3-Clause "New" or "Revised" License
80 stars 52 forks source link

Allow returning of empty array from multicheckboxes (using use_hidden_element) #149

Open tempfirstuser opened 3 years ago

tempfirstuser commented 3 years ago

Bug Report

Q A
Version(s) 2.15.1

Summary

I have multicheckoxes. I want to have ability to return empty array if non of checkboxes is checked. I use use_hidden_element to return hidden input element instead but it returns empty string instead of empty array.

This is my fieldset config:

"productCategories" => [
    'type' => MultiCheckbox::class,
    'name' => 'categories',
    'options' => [
        'use_hidden_element' => true,
    ],
],

this is my input filter config:

"productCategories" => [
    'name' => 'categories',
    'type' => ArrayInput::class,
    //'required' => true,
    'required'          => false,
    'allow_empty'       => true,
    'continue_if_empty' => true,
    'filters' => [
            ['name' => ToInt::class],
    ],
],

this is generated hidden input:

<input type="hidden" name="product[categories]" value="">

this is generated checkbox input:

<input type="checkbox" name="product[categories][]" value="12">
<input type="checkbox" name="product[categories][]" value="34">
<input type="checkbox" name="product[categories][]" value="56">

and as result I've got this exception:

Additional information:
Laminas\InputFilter\Exception\InvalidArgumentException

File:

    /vendor/laminas/laminas-inputfilter/src/ArrayInput.php:26

Message:

    Value must be an array, string given.

Stack trace:

    #0 /vendor/laminas/laminas-inputfilter/src/BaseInputFilter.php(544): Laminas\InputFilter\ArrayInput->setValue()
    #1 /vendor/laminas/laminas-inputfilter/src/BaseInputFilter.php(206): Laminas\InputFilter\BaseInputFilter->populate()
    #2 /vendor/laminas/laminas-inputfilter/src/BaseInputFilter.php(540): Laminas\InputFilter\BaseInputFilter->setData()
    #3 /vendor/laminas/laminas-inputfilter/src/BaseInputFilter.php(206): Laminas\InputFilter\BaseInputFilter->populate()
    #4 /vendor/laminas/laminas-form/src/Form.php(522): Laminas\InputFilter\BaseInputFilter->setData()
froschdesign commented 3 years ago

@tempfirstuser Unfortunately, I cannot reproduce the error message. Can you provide a full example which allows to reproduce the problem? Another option is an unit test. Thanks!

Slamdunk commented 3 years ago

For sake of completeness, this has also been discussed in Slack: https://laminas.slack.com/archives/C4QBQUEG5/p1623930860223800 image

tempfirstuser commented 3 years ago

@froschdesign , I have this generated html code:

<input type="hidden" name="categories" value="">

<input type="checkbox" name="categories[]" value="12">
<input type="checkbox" name="categories[]" value="34">
<input type="checkbox" name="categories[]" value="56">

if I checked some checkboxes I will have POST array of categories, something like this:

$_POST = [
    'categories' => [
        12,
        34,
        56
    ]
];

But if I will not check any of checkboxes I will have value from hidded input like this:

$_POST = [
    'categories' => ''
];

which means instead of array I will get empty string. Was this helpful? Currently, I don't use 'use_hidden_element' => true, and check if categories is isset() within POST and if not I add categories with value of empty array to the POST.

froschdesign commented 3 years ago

@tempfirstuser

I have the same HTML output and can not reproduce the error message:

File:

/vendor/laminas/laminas-inputfilter/src/ArrayInput.php:26

Message:

Value must be an array, string given.

So I need the definition of your form with input-filter.

tempfirstuser commented 3 years ago

@froschdesign , actually, I have nested array. I was trying to simplify the question. I have modified my post/issue at the top. fieldset and filter from the top is all what I have. In reality I have something nested like this:

$_POST = [
    'product' => [
        'categories' => ''
    ]
];

Do you have the same empty string:

$_POST = [
    'categories' => ''
];

? Or do you have empty array like this:

$_POST = [
    'categories' => []
];

?

froschdesign commented 3 years ago

@tempfirstuser

I have modified my post/issue at the top.

Okay, this helps! 👍

Please try to override the following:

https://github.com/laminas/laminas-form/blob/ed6c9722c2b3b3f8825b2ce626c8d0da29a72594/src/View/Helper/FormMultiCheckbox.php#L257-L260

With:

$hiddenAttributes = [
    'name'  => static::getName($element),
    'value' => $uncheckedValue,
];

This will not work because the empty / unchecked value is always added to the array!