zendframework / zend-inputfilter

InputFilter component from Zend Framework
BSD 3-Clause "New" or "Revised" License
64 stars 50 forks source link

Exception when supplying non-array data to an ArrayInput #179

Closed ghost closed 5 years ago

ghost commented 5 years ago

This issue is more a query than a bug report, but I wasn't sure of the correct route to address the problem - whether that might be taking a different approach or in suggesting a fix.

One of the inputs on my input filter is using ArrayInput and is expecting an array of values. If I specify a string for the value in the data passed to setData() on the input filter then setValue() on the ArrayInput throws an exception because it's expecting an array.

Potentially the user might supply the request data incorrectly so it should cater for that scenario. Is it really necessary for me to pre-filter any array values in my own code before calling the input filter? That seems like something that should really be handled by the library; i.e. if a non-array value is passed to an array input, rather than throwing an exception, is recorded as an error against the input for retrieval via getMessages().

Other options:

Code to reproduce the issue

Input filter:

use Zend\InputFilter\InputFilter;

class MyInputFilter extends InputFilter
{
    public function init(): void
    {
        $this->add([
            'name' => 'array_of_values',
            'type' => \Zend\InputFilter\ArrayInput::class,
        ]);
    }
}

Call:

$inputFilter = new MyInputFilter();
$inputFilter->setData([
    'array_of_values' => 'string_value',
]);

Expected results

Error reporting via the input filter itself.

Actual results

Zend\InputFilter\Exception\InvalidArgumentException Value must be an array, string given.

froschdesign commented 5 years ago

@kgrey

Use CollectionInputFilter (overkill?)

This is the correct solution for two reasons:

  1. The input is called Array-Input why other data types should be allowed?

You can use:

$value = 'string_value';
$inputFilter->setData(
    [
        'array_of_values' => is_array($value) ? $value : [],
    ]
);
  1. With the collection input-filter you can filter and validate the content of the given array data.

The problem with your current input-filter:

$inputFilter->setData(
    [
        'array_of_values' => [[[[]]]],
    ]
);
var_dump($inputFilter->isValid()); // true

$inputFilter->setData(
    [
        'array_of_values' => [
            [
                1,
                2,
                3,
            ],
            [
                [
                    new stdClass(),
                ]
            ],
            'foobar'
        ],
    ]
);
var_dump($inputFilter->isValid()); // true

Please look also at the optional input-filter if you work with arrays of data: https://docs.zendframework.com/zend-inputfilter/optional-input-filters/

ghost commented 5 years ago

That's very useful. Thanks for the clarification. I'll give it a try.