7

Official PHP documentation states that filter_var_array() supports array filtering in the following format:

$data = array(
    'testarray'    => array('2', '23', '10', '12')
);

$args = array(
    'testarray'    => array('filter'    => FILTER_VALIDATE_INT,
                            'flags'     => FILTER_FORCE_ARRAY
                           )    
);

$myinputs = filter_var_array($data, $args);

However, if the array in question is multi-dimensional and requires different filters for different parts, how would you approach defining filtering options?

As an example:

$data = array(
    'testhash'    => array('level1'=>'email', 
                           'level2'=> array('23', '10', '12'))
);

1 Answer 1

11

Idea 1

Consider using FILTER_CALLBACK. In this way, you can write a callback function that itself uses the filter extension, thus providing a recursive ability.

function validate_array($args) {
    return function ($data) use ($args) {
        return filter_input_array($data, $args);
    };
}

This will generate the callback functions.

$args = array(
    'user' => array(
        'filter' => FILTER_CALLBACK,
        'options' => validate_array(array(
            'age' => array('filter' => FILTER_INPUT_INT),
            'email' => array('filter' => FILTER_INPUT_EMAIL)
        ))
    )
);

This is what the config array would then look like.

Idea 2

Do not hesitate to pat me on the back for this one because I am quite proud of it.

Take an arg array that looks like this. Slashes indicate depth.

$args = array(
    'user/age' => array('filter' => FILTER_INPUT_INT),
    'user/email' => array('filter' => FILTER_INPUT_EMAIL),
    'user/parent/age' => array('filter' => FILTER_INPUT_INT),
    'foo' => array('filter' => FILTER_INPUT_INT)
);

Assume your data looks something like this.

$data = array(
    'user' => array(
        'age' => 15,
        'email' => '[email protected]',
        'parent' => array(
            'age' => 38
        )
    ),
    'foo' => 5
);

Then, you can generate an array of references that map keys such as 'user/age' to $data['user']['age']. In final production, you get something like this:

function my_filter_array($data, $args) {
    $ref_map = array();
    foreach ($args as $key => $a) {
        $parts = explode('/', $key);
        $ref =& $data;
        foreach ($parts as $p) $ref =& $ref[$p];
        $ref_map[$key] =& $ref;
    }
    return filter_var_array($ref_map, $args);
}

var_dump(my_filter_array($data, $args));

Now the only question is how you deal with the mismatch between the validation record and the original data set. This I cannot answer without knowing how you need to use them.

Sign up to request clarification or add additional context in comments.

5 Comments

This is indeed a good idea, +1, my only hesitation now is that it effectively changes the nature of config array from being purely declarative to partially imperative. which, in my experience, is almost always bad for code clarity and predictable behavior.
I know it is messy. I am working out something that results in a cleaner config.
Ah, finally, after trying half a dozen ideas I found a solution that works quite beautifully.
oh, this is indeed quite cool, and even though I was using a similar approach to specifying php-xml conversion config, I didn't think of it for filtering purposes! you deserve your checkmark :)
Idea 1 wont work in your validate_array function will be called with the values of the user array. validate_array will be called 3 times and $data will be 15, "[email protected]", 38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.