Search code examples
phparraysarray-filter

PHP array_filter on array containing multiple arrays


I'm using array_filter in PHP to split an array containing multiple arrays when the value of a key named type matches a specific string. Here's what this looks like:

Sample Array

$arr[] = Array (
    [0] => Array ( [type] => Recurring ... )
    [1] => Array ( [type] => Single ... )
)

Functions

function recurring($value)
{
    return ($value['type'] == 'Recurring');
}

function single($value)
{
    return ($value['type'] == 'Single');
}

Split Arrays

$recurring = array_filter($arr, 'recurring');
$single    = array_filter($arr, 'single');

This works, but I was curious if there was a way to simplify it so that I could create additional filtered arrays in the future without creating a new function for each.

I've started setting up a single function using a closure, but I'm not sure how to do it. Any ideas?

function key_type($value, $key, $string) {
    return $key == 'type' && $value == $string;
}

$recurring = array_filter($arr, 
key_type('Recurring'), ARRAY_FILTER_USE_BOTH);

$single = array_filter($pricing, 
key_type('Single'), ARRAY_FILTER_USE_BOTH);

Solution

  • You could actually do what you proposed in your question. You just need to have the key_type() function return a callable function, which is what array_filter expects as the second parameter. You can return an anonymous function and pass the argument into the anonymous function using the use keyword as CBroe mentioned in the comments.

    Here is an example:

    function key_type($key) {
        return function($value) use ($key) {
            return $value['type'] == $key;
        };
    }
    
    $arr = array(
        array('type'=>'Recurring'),
        array('type'=>'Single')
    );
    print_r(array_filter($arr, key_type('Single'), ARRAY_FILTER_USE_BOTH));
    

    The above code will output:

    Array ( [1] => Array ( [type] => Single ) )
    

    The beauty of this method is that if you need to change the logic for all instances where you need to use your filter, you just have to change it one time in your key_type function.