Search code examples
phparraysmultidimensional-arrayassociative-arrayunset

How to remove item from multidimensional, associative array in PHP


I have a multi dimensional, associative array. I'm trying to find a way to remove spesific items from the array, regardless of their position.

The array is used for building the navigation menu on a website. Sub items will always be in an array called "children" within its parent item. The key "children" is not present for items that have no children, if that makes things easier.

"menuid" is the item's id in the database, but since there are multiple types of items (pages, category pages, galleries, urls and so forth), the same menuid may occur multiple times. I want to be able to remove items by "menuid" and "menutype".

I'm able to delete an item based on menuid alone, but only from the root array:

$key = array_search(15, array_column($array, 'menuid'));
unset($array[$key]);

I prefer to do it with a function, but I have the same problem here. This will also only remove items if they're in the root of the array.

function removeItem($array, $menutype, $menuid)
{
   foreach ($array as $key => $value)
   {
      if (is_array($value)) 
      {
         if (isset($value['menutype']) && isset($value['menuid']) && $value['menutype'] == $menutype && $value['menuid'] == $menuid)
         {
            unset($array[$key]);
         }
      }
   }
   return $array;
}

$removeItem = removeItem($array, 'simplepage', 11);

I have not found a way to delete items from anywhere in the array based on both "menutype" and "menuid".

Here's an example of the array. What would I do to delete the item with menuid 13 and menutype "posts_category"?

Array
(
    [0] => Array
        (
            [menutarget] => _parent
            [menulink] => /
            [rewritename] => Home
            [menutype] => url
            [menuid] => 2
            [id] => Home
        )

    [1] => Array
        (
            [id] => Category 3
            [menuid] => 15
            [menutype] => posts_category
            [rewritename] => Category_3
            [menulink] => 
            [menutarget] => _parent
        )

    [2] => Array
        (
            [id] => Page 1
            [menuid] => 11
            [menutype] => page
            [rewritename] => page_1
            [menulink] => 
            [menutarget] => _parent
            [children] => Array
                (
                    [0] => Array
                        (
                            [id] => Category 1
                            [menuid] => 13
                            [menutype] => posts_category
                            [rewritename] => Category_1
                            [menulink] => 
                            [menutarget] => _parent
                            [children] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] => Category 2
                                            [menuid] => 14
                                            [menutype] => posts_category
                                            [rewritename] => Category_2
                                            [menulink] => 
                                            [menutarget] => _parent
                                        )

                                )

                        )

                )

        )

    [3] => Array
        (
            [menutarget] => _parent
            [menulink] => 
            [rewritename] => Videotest
            [menutype] => page
            [menuid] => 10
            [id] => Videotest
        )
)

Solution

  • You want to recursively check it:

    function removeItem(&$array, $menutype, $menuid)
    {
        foreach ($array as $key => &$value) {
            if (isset($value['menutype'], $value['menuid']) && $value['menutype'] == $menutype && $value['menuid'] == $menuid) {
                unset($array[$key]);
            } elseif (isset($value['children']) && is_array($value['children'])) {
                removeItem($value['children'], $menutype, $menuid);
            }
        }
    }
    
    removeItem($arr, 'posts_category', 13);
    
    print_r($arr);