Recursively deleting elements from an array
I had a need recently to delete items from a nested associative array and also any empty sub-arrays. My initial thought was to use array_walk_recursive, but this doesn’t work as you can’t unset nested elements and you only have access to the leaves. Clearly I needed a recursive function.
I’m sure that this has been done many times before, but this is my solution:
/**
* Remove any elements where the callback returns true
*
* @param array $array the array to walk
* @param callable $callback callback takes ($value, $key, $userdata)
* @param mixed $userdata additional data passed to the callback.
* @return array
*/
function array_walk_recursive_delete(array &$array, callable $callback, $userdata = null)
{
foreach ($array as $key => &$value) {
if (is_array($value)) {
$value = array_walk_recursive_delete($value, $callback, $userdata);
}
if ($callback($value, $key, $userdata)) {
unset($array[$key]);
}
}
return $array;
}
with this test:
class FunctionsTest extends \PHPUnit_Framework_TestCase
{
public function testArrayWalkRecursiveDelete()
{
$array = [
'a'=> 'a',
'b'=> null,
'c' => [
'a' => null,
'b' => 'b',
],
'd' => [
'a' => null
]
];
$result = array_walk_recursive_delete($array, function ($value, $key) {
if (is_array($value)) {
return empty($value);
}
return ($value === null);
});
$expected = [
'a'=> 'a',
'c' => [
'b' => 'b',
],
];
$this->assertSame($expected, $result);
}
}
This is very similar to how array_walk_recursive works except that I return the altered array rather than a boolean as it’s a recursive function.
The test shows how I use it:
$result = array_walk_recursive_delete($array, function ($value, $key) {
if (is_array($value)) {
return empty($value);
}
return ($value === null);
});
If the callback returns true, then the element is deleted from the array, so for my case, I return true if the value is an empty array or null.



Something like this should do the trick too
https://gist.github.com/david4worx/1a991a705a52d8f9b16b
Ps; you forgot the 3rd param in your docblocks of the function.
Thanks David. I've updated the docblock.