2

I'm attempting to filter $_POST data, and later render it as HTML, that is nested arrays, going about three levels deep. My structure looks something like this:

Array
(
    [books] ==> Array
    (
        [book1] ==> Array
        (
            [0] ==> Title
            [1] ==> Author                    
        )
        [book2] ==> Array
        (
            [0] ==> Title
            [1] ==> Author
        )
    )

    [articles] ==> Array
    (
        [article1] ==> Array
        (
            [0] ==> Journal
            [1] ==> Title                    
        )
        [article2] ==> Array
        (
            [0] ==> Journal
            [1] ==> Title
        )
    )
)

I have this gut feeling there's a way to use foreach loops and filter_input_arrays (with array and sanitize arguments), but I'm pretty new to PHP and having a hard go at it. I have successfully filtered other arrays, but I'm wondering if there is a graceful way to iterate through the arrays, filtering them, and returning an object with the same structure.

4

3 回答 3

2

This will recursively filter your data and return an object as requested, choose your filter method in the sanitize function. You can go several levels deep with this function, and have asymmetric structures.

$arrayData = array (
    'books' => array ( array ( 'Title1','Author1' ), array ( 'Title2','Author2' )),
    'articles' => array ( array ( 'Journal3','Title3' ), array ( 'Journal3','Title3' ))

);

function arrayFilter($arrayIn){
    $output = null;
    if (is_array($arrayIn)){
        foreach ($arrayIn as $key=>$val){
            if (is_array($val)){
                $output->{$key} = arrayFilter($val);
            } else {
                $output->{$key} = sanitize($val);
            }
        }
    } else {
        $output->{$key} = sanitize($val);
    }
    return $output;
}

function sanitize($val)
{
    //insert your preferred data filter here
    return addslashes('filtered: '.$val);
}

print_r (arrayFilter($arrayData));

Output:

stdClass Object
(
    [books] => stdClass Object
        (
            [0] => stdClass Object
                (
                    [0] => filtered: Title1
                    [1] => filtered: Author1
                )

            [1] => stdClass Object
                (
                    [0] => filtered: Title2
                    [1] => filtered: Author2
                )

        )

    [articles] => stdClass Object
        (
            [0] => stdClass Object
                (
                    [0] => filtered: Journal3
                    [1] => filtered: Title3
                )

            [1] => stdClass Object
                (
                    [0] => filtered: Journal3
                    [1] => filtered: Title3
                )

        )

)
于 2012-08-10T13:58:07.273 回答
0

I can see two things here you want to validate the input for:

  1. The structure - A book is not complete if it has not a title or not an author for example.
  2. Each fields data - A book's title much not contain whitespace at it's start and end for example.

Maybe this is a bit too simplified, but what I'd like to highlight is that you need to put your understanding of these data-types into your validation:

function books_is_valid(array $books) {
     foreach ($books as $book) {
         if (!$book_is_valid($bool) {
             return false;
         }
     }
     return true;
}

function book_is_valid(array $book) {
    if (!count($book) === 2) return false;
    if (!array_keys($book) === array(0, 1)) return false;
    if (!book_title_is_valid($book[0])) return false;
    if (!book_author_is_valid($book[1])) return false;
    return true;
}

book_title_is_valid($title) {
     ... # do your checks, return bool
}

book_author_is_valid($author) {
     ... # do your checks, return bool
}

Like your data-structure is complex, so is your validation. As you even have different complex data-types like book and article, you can write yourself some general functions to support these type of input so you can move duplicated code into functions of it's own and remove the duplication later on.

You can then use your specific filters with the filter_input_array function by making use of the FILTER_CALLBACK:

$args = array(
    'books'    => array('filter'  => FILTER_CALLBACK,
                        'options' => 'books_is_valid', 
                       ),
    'articles' => array('filter'  => FILTER_CALLBACK,
                        'options' => 'articles_is_valid', 
                       ),
);

$myinputs = filter_input_array(INPUT_POST, $args);

var_dump($myinputs);

Note that this is validation only. So it will tell you whether or not the form submit in total was valid or not.

于 2012-08-10T13:38:21.230 回答
0

see url:-- Filter multidimensional arrays

array_filter accepts a callback that you can use to customize the filtering logic. This would work:

$filtered = array_filter($array, function($el) { return !empty($el['mob']; });

Here the callback is supplied as an anonymous function.

于 2012-08-10T13:42:42.150 回答