You only want to remove a key if it's not named access and the value is not a nested array. This way, you keep any intermediate arrays.

You can't use array_filter(), because it only receives the values, not the keys. So do it in your foreach loop.

function array_filter_recursive($input)
{
    foreach ($input as $key => &$value) {
        if (is_array($value)) {
            $value = array_filter_recursive($value);
            if (empty($value)) {
                unset($input[$key]);
            }
        } elseif ($key != 'access') {
            unset($input[$key]);
        }
    }
    return $input;
}
Answer from Barmar on Stack Overflow
🌐
PHP
php.net › manual › en › function.array-walk-recursive.php
PHP: array_walk_recursive - Manual
One other silly thing you might try first is something like this: <?php // Resist the urge to do this, it doesn't work. $filtered = array_walk_recursive($unfiltered,'filter_function'); ?> Of course, $filtered is just TRUE afterwards, not the filtered results you were wanting.
🌐
WP Scholar
wpscholar.com › home › filtering multi-dimensional arrays in php
Filtering Multi-Dimensional Arrays in PHP - WP Scholar
August 14, 2015 - /** * Recursively filter an array * * @param array $array * @param callable $callback * * @return array */ function array_filter_recursive( array $array, callable $callback = null ) { $array = is_callable( $callback ) ? array_filter( $array, $callback ) : array_filter( $array ); foreach ( $array as &$value ) { if ( is_array( $value ) ) { $value = call_user_func( __FUNCTION__, $value, $callback ); } } return $array; } The function works just like PHP’s array_filter() and even allows for a custom callback if you want to provide one.
🌐
GitHub
gist.github.com › 1690140
PHP array_filter_recursive function · GitHub
/** function array_filter_recursive * * Exactly the same as array_filter except this function * filters within multi-dimensional arrays * * @param array * @param string optional callback function name * @param bool optional flag removal of empty arrays after filtering * @return array merged array */ function array_filter_recursive($array, $callback = null, $remove_empty_arrays = false) { foreach ($array as $key => & $value) { if (is_array($value)) { $value = call_user_func_array(__FUNCTION__, array($value, $callback, $remove_empty_arrays)); if ($remove_empty_arrays && !
Top answer
1 of 8
33

From the PHP array_filter documentation:

//This function filters an array and remove all null values recursively. 

<?php 
  function array_filter_recursive($input) 
  { 
    foreach ($input as &$value) 
    { 
      if (is_array($value)) 
      { 
        $value = array_filter_recursive($value); 
      } 
    } 

    return array_filter($input); 
  } 
?> 

//Or with callback parameter (not tested) : 

<?php 
  function array_filter_recursive($input, $callback = null) 
  { 
    foreach ($input as &$value) 
    { 
      if (is_array($value)) 
      { 
        $value = array_filter_recursive($value, $callback); 
      } 
    } 

    return array_filter($input, $callback); 
  } 
?>
2 of 8
11

Should work

$count = array_sum(array_map(function ($item) {
  return ((int) !is_null($item['pts_m'])
       + ((int) !is_null($item['pts_mreg'])
       + ((int) !is_null($item['pts_cg']);
}, $array);

or maybe

$count = array_sum(array_map(function ($item) {
  return array_sum(array_map('is_int', $item));
}, $array);

There are definitely many more possible solutions. If you want to use array_filter() (without callback) remember, that it treats 0 as false too and therefore it will remove any 0-value from the array.

If you are using PHP in a pre-5.3 version, I would use a foreach-loop

$count = 0;
foreach ($array as $item) {
  $count += ((int) !is_null($item['pts_m'])
          + ((int) !is_null($item['pts_mreg'])
          + ((int) !is_null($item['pts_cg']);
}

Update

Regarding the comment below:

Thx @kc I actually want the method to remove false, 0, empty etc

When this is really only, what you want, the solution is very simple too. But now I don't know, how to interpret

My expected result here would be 5.

Anyway, its short now :)

$result = array_map('array_filter', $array);
$count = array_map('count', $result);
$countSum = array_sum($count);

The resulting array looks like

Array
(
[147] => Array
    (
        [pts_mreg] => 1
        [pts_cg] => 1
    )    
[158] => Array
    (
    )

[159] => Array
    (
        [pts_mreg] => 1
        [pts_cg] => 1
    )

)
🌐
Sujip Thapa's Blog
sujipthapa.com › blog › a-custom-php-function-for-recursive-array-filtering
A Custom PHP Function for Recursive Array Filtering
Here’s the initial version of the function: public function filterDataRecursively($array = []) { foreach ($array as &$value) { if (is_array($value)) { $value = $this->filterDataRecursively($value); } } return array_filter($array); }
🌐
PHP Freaks
forums.phpfreaks.com › php coding › php coding help
Recursively remove all array elements which are not of given type - PHP Coding Help - PHP Freaks
May 30, 2019 - Can anyone let me know what I am doing wrong. I am sure it will (after the fact) be obvious, but I don't see it right now. Wish to remove all array elements which do not implement ValidatorCallbackInterface. Thanks
Find elsewhere
🌐
W3Schools
w3schools.com › php › func_array_filter.asp
PHP array_filter() Function
PHP Overview PHP Array · array() array_change_key_case() array_chunk() array_column() array_combine() array_count_values() array_diff() array_diff_assoc() array_diff_key() array_diff_uassoc() array_diff_ukey() array_fill() array_fill_keys() array_filter() array_flip() array_intersect() array_intersect_assoc() array_intersect_key() array_intersect_uassoc() array_intersect_ukey() array_key_exists() array_keys() array_map() array_merge() array_merge_recursive() array_multisort() array_pad() array_pop() array_product() array_push() array_rand() array_reduce() array_replace() array_replace_recursi
🌐
W3Schools
w3schools.com › php › func_array_replace_recursive.asp
PHP array_replace_recursive() Function
The array_replace_recursive() function replaces the values of the first array with the values from following arrays recursively. Tip: You can assign one array to the function, or as many as you like.
Top answer
1 of 3
7

You could combine array_map and array_filter in an recursive called function. Something like this could work for you.

function filterNotNull($array) {
    $array = array_map(function($item) {
        return is_array($item) ? filterNotNull($item) : $item;
    }, $array);
    return array_filter($array, function($item) {
        return $item !== "" && $item !== null && (!is_array($item) || count($item) > 0);
    });
}
2 of 3
2

Don't need to reinvent recursion yourself. You can use RecursiveCallbackFilterIterator:

$iterator = new RecursiveIteratorIterator(
    new RecursiveCallbackFilterIterator(
        new RecursiveArrayIterator($arr),
        function ($value) {
            return $value !== null && $value !== '';
        }
    )
);

$result = iterator_to_array($iterator);

Here is working demo.

You should try to use as much stuff from Standard PHP Library (SPL) as you can.

UPDATE: As it is stated in the comments, the solution with iterator not actually suits for this purpose.

In the comments to the array_walk_recursive function you can find the implementation of walk_recursive_remove function:

function walk_recursive_remove (array $array, callable $callback) { 
    foreach ($array as $k => $v) { 
        if (is_array($v)) { 
            $array[$k] = walk_recursive_remove($v, $callback); 
        } else { 
            if ($callback($v, $k)) { 
                unset($array[$k]); 
            } 
        } 
    } 

    return $array; 
} 

This generalized version of recursion function takes criteria in the form of callback. Having this function you can remove empty elements like this:

$result = walk_recursive_remove($arr, function ($value) {
    return $value === null || $value === '';
});

Here is working demo.

🌐
Tutorialspoint
tutorialspoint.com › php › php_function_array_filter.htm
PHP - Function array_filter()
It returns the filtered array. ... <?php function odd($var) { return($var & 1); } function even($var) { return(!($var & 1)); } $input1 = array("a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5); $input2 = array(6, 7, 8, 9, 10, 11, 12); echo "Odd Values:\n"; print_r(array_filter($input1, "odd")); echo "Even Values:\n"; print_r(array_filter($input2, "even")); ?>
🌐
W3Schools
w3schools.com › php › func_array_walk_recursive.asp
PHP array_walk_recursive() Function
array_walk_recursive(array, myfunction, parameter...) ... If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail: sales@w3schools.com · If you want to report an error, or if you want to make a suggestion, send us an e-mail: help@w3schools.com · HTML Tutorial CSS Tutorial JavaScript Tutorial How To Tutorial SQL Tutorial Python Tutorial W3.CSS Tutorial Bootstrap Tutorial PHP Tutorial Java Tutorial C++ Tutorial jQuery Tutorial
🌐
DEV Community
dev.to › gbhorwood › php-doing-recursion-with-recursive-iteratoriterators-fj1
php: doing recursion with recursive iterator(iterator)s - DEV Community
June 5, 2024 - so, now we can traverse our entire array and apply the custom filters or transformations of our choosing. this is good, but it would be much better if we could write up a generic recursion function that took filters and transformations as arguments.
🌐
David Walsh
davidwalsh.name › get-array-values-with-php-recursively
Get Array Values Recursively with PHP
February 12, 2016 - // http://php.net/manual/en/fu... function array_values_recursive($array) { $flat = array(); foreach($array as $value) { if (is_array($value)) { $flat = array_merge($flat, array_values_recursive($value)); } else { $flat[] = $value; } } return $flat; }...