Search code examples
phparrayspostmultidimensional-arraysanitization

POST filter_input_array & non-specific multi-dimensional arrays


I've just started programmatically sanitizing $_POST inputs as part of a new PHP project and I've come across this issue - the posted values include multi-select values, which are posted as further arrays inside the POST array.

Array
(
    [return_url] => dataset
    [dataset_name] => Retail
    [dataset_collection] => Array
        (
            [0] => 183
            [1] => 184
        )

    [dataset_purpose] => Array
        (
            [0] => 186
            [1] => 188
            [2] => 190
            [3] => 191
        )

    [dataset_security] => Array
        (
            [0] => 192
            [1] => 194
        )

    [dataset_location] => internal
    [dataset_processor_name] => XXX
    [dataset_processor_role] => XXX
    [dataset_processor_email] => XXX@YYY
    [dataset_processor_tel] => XXX
)

I've built a filter array to push the POST values through via filter_input_array and very quickly realized this wasn't processing the data correctly...

$filters = array (
        "return_url" => FILTER_SANITIZE_STRING,
        "dataset_name" => FILTER_SANITIZE_STRING,
        "dataset_collection" => FILTER_REQUIRE_ARRAY,
        "dataset_purpose" => FILTER_REQUIRE_ARRAY,
        "dataset_security" => FILTER_REQUIRE_ARRAY,
        "dataset_location" => FILTER_SANITIZE_STRING,
        "dataset_processor_name" => FILTER_SANITIZE_STRING,
        "dataset_processor_role" => FILTER_SANITIZE_STRING,
        "dataset_processor_email" => FILTER_VALIDATE_EMAIL,
        "dataset_processor_tel" => FILTER_SANITIZE_STRING
        );
    
$posted_data = filter_input_array(INPUT_POST, $filters);

Array
(
    [return_url] => dataset
    [dataset_name] => Customers - Retail
    [dataset_collection] => 
    [dataset_purpose] => 
    [dataset_security] => 
    [dataset_location] => internal
    [dataset_processor_name] => XXX
    [dataset_processor_role] => XXX
    [dataset_processor_email] => XXX@YYY
    [dataset_processor_tel] => XXX
)

I've found this suggestion of using a recursive array walk to step through every stage of the array, but that doesn't take into account the differing filter types.

I know, in theory, pushing every value through FILTER_SANITIZE_STRING will work, but does anyone know of a way to dynamically creating the $filter array, for example, based on the number of values in POST, or is the best method to simply run the filter_input_array initially on the POST array then manually array walk the dataset arrays in manually..?


Solution

  • Ok, I found the result (in plain sight) here in the PHP manual...

    I needed to insert sub-arrays against the appropriate values in the the filter, as follows...

    $filters = array (
            "return_url" => FILTER_SANITIZE_STRING,
            "dataset_name" => FILTER_SANITIZE_STRING,
            "dataset_collection" => array('filter'  => FILTER_VALIDATE_INT,
                                        'flags'     => FILTER_REQUIRE_ARRAY
                                        ),
            "dataset_purpose" => array('filter'  => FILTER_VALIDATE_INT,
                                        'flags'     => FILTER_REQUIRE_ARRAY
                                        ),
            "dataset_security" => array('filter'  => FILTER_VALIDATE_INT,
                                        'flags'     => FILTER_REQUIRE_ARRAY
                                        ),
            "dataset_location" => FILTER_SANITIZE_STRING,
            "dataset_processor_name" => FILTER_SANITIZE_STRING,
            "dataset_processor_role" => FILTER_SANITIZE_STRING,
            "dataset_processor_email" => FILTER_VALIDATE_EMAIL,
            "dataset_processor_tel" => FILTER_SANITIZE_STRING
            );
    

    This returned the correct array...

    Array
    (
        [return_url] => dataset
        [dataset_name] => Customers - Retail
        [dataset_collection] => Array
            (
                [0] => 183
                [1] => 184
            )
    
        [dataset_purpose] => Array
            (
                [0] => 186
                [1] => 188
                [2] => 190
                [3] => 191
            )
    
        [dataset_security] => Array
            (
                [0] => 192
                [1] => 194
            )
    
        [dataset_location] => internal
        [dataset_processor_name] => XXX
        [dataset_processor_role] => XXX
        [dataset_processor_email] => XXX@YYY
        [dataset_processor_tel] => XXX
    )