以递归方式从多维数组中删除特定键

I am trying to create a function to remove keys from a dynamic multidimensional array, i need to give:

removeByIndex(['hello', 'my', 'world']);

And then the function needs to do this:

unset($array['hello']['my']['world']);

The number of indexes are dynamic, example:

removeByIndex(['hello', 'my']); // Do: unset($array['hello']['my']);
removeByIndex(['hello']); // Do: unset($array['hello']);

I tried to use some foreach loops, but i didn't find a solution yet.

Any help will be welcome.

No need for eval() with a little bit of referencing.

/**
 * Remove index from multi-dimensional array.
 *
 * @param array $array
 *   The array to remove the index from.
 * @param array $indices
 *   Indexed array containing the indices chain up to the index that should be
 *   removed.
 * @return
 *   The array with the index removed.
 * @throws \InvalidArgumentException
 *   If the index does not exist within the array.
 */
function removeByIndex(array $array, array $indices) {
  // Create a reference to the original array.
  $a =& $array;

  // Count all passed indices, remove one because arrays are zero based.
  $c = count($indices) - 1;

  // Iterate over all passed indices.
  for ($i = 0; $i <= $c; ++$i) {
    // Make sure the index to go down for deletion actually exists.
    if (array_key_exists($indices[$i], $a)) {
      // This is the target if we reached the last index that was passed.
      if ($i === $c) {
        unset($a[$indices[$i]]);
      }
      // Make sure we have an array to go further down.
      elseif (is_array($a[$indices[$i]])) {
        $a =& $a[$indices[$i]];
      }
      // Index does not exist since there is no array to go down any further.
      else {
        throw new \InvalidArgumentException("{$indices[$i]} does not exist.");
      }
    }
    // Index does not exist, error.
    else {
      throw new \InvalidArgumentException("{$indices[$i]} does not exist.");
    }
  }

  return $array;
}

print_r(removeByIndex(
  [ "test1" => [ "test2" => [ "test3" => "test" ] ], "test4" => "test" ],
  [ "test1", "test2", "test3" ]
));

Since I mentioned it in the comments, one could (micro-)optimize the function, but I advice against it, since it is less readable and might confuse some programmers.

<?php

function removeByIndex(array $array, array $indices) {
  $a =& $array;
  $c = count($indices) - 1;
  $i = 0;
  do {
    if (array_key_exists($indices[$i], $a)) {
      if ($i === $c) {
        unset($a[$indices[$i]]);
        return $array;
      }
      elseif (is_array($a[$indices[$i]])) {
        $a =& $a[$indices[$i]];
      }
      else break;
    }
    else break;
  }
  while (++$i);
  throw new \InvalidArgumentException("{$indices[$i]} does not exist.");
}

Based on the briliant @Fleshgrinder answer, i am using this final version:

function removeByIndex($vars, $indexes) {
    if ( ! is_array($indexes)) {
        throw new \Exception('Array expected');
    }

    $array = & $vars;

    $qtd_indexes = count($indexes);

    for ($i = 0; $i < $qtd_indexes; $i++) {
        if ( ! array_key_exists($indexes[$i], $array)) {
          throw new \Exception($indexes[$i] . " doesn't exist");
        }

        // Check if it is the target entry
        if ($i === $qtd_indexes - 1) {
            unset($array[$indexes[$i]]);
        } elseif (is_array($array[$indexes[$i]])) { // Check if exists one more level
            $array = & $array[$indexes[$i]];
        } else {
            // If it isn't the target and it isn't an array, throw exception
            throw new \Exception("Content of '" . $indexes[$i] . "' isn't an array");
        }
    }

    return $vars;
}

I was researched for a couple of hours for this solution, nowhere found an optimal solution. so, i wrote it by myself

function allow_keys($arr, $keys)
    {
        $saved = [];

        foreach ($keys as $key => $value) {
            if (is_int($key) || is_int($value)) {
                $keysKey = $value;
            } else {
                $keysKey = $key;
            }
            if (isset($arr[$keysKey])) {

                $saved[$keysKey] = $arr[$keysKey];
                if (is_array($value)) {

                    $saved[$keysKey] = allow_keys($saved[$keysKey], $keys[$keysKey]);
                }
            }
        }
        return $saved;
    }

use: example

$array = [
        'key1' => 'kw',
        'loaa'=> ['looo'],
        'k'    => [
            'prope' => [
                'prop'  => ['proo', 'prot', 'loolooo', 'de'],
                'prop2' => ['hun' => 'lu'],
            ],
            'prop1' => [

            ],
        ],
    ];

call: example

allow_keys($array, ['key1', 'k' => ['prope' => ['prop' => [0, 1], 'prop2']]])

output:

Array ( [key1] => kw [k] => Array ( [prope] => Array ( [prop] => Array ( [0] => proo [1] => prot ) [prop2] => Array ( [hun] => lu ) ) ) ) 

so you get only needed keys from the multidimensional array. it is not limited only for "multidimensional", you can use it by passing an array like

['key1', 'loaa']

output you get:

Array ( [key1] => kw [loaa] => Array ( [0] => looo ) )

i'm writing it here for reason that this topic is one of the first when you type on google

recursive remove keys multidimensional php

hope someone helps this one, as i searched a lot, and nothing found. cheers!