отключить элемент массива посредством ссылки

Я могу получить доступ в любом месте внутри многомерного массива с помощью ссылочного метода. И я могу изменить его ценность. Например:

$conf = array( 'type' => 'mysql', 'conf' => array( 'name' => 'mydatabase', 'user' => 'root', 'pass' => '12345', 'host' => array( '127.0.0.1', '88.67.45.123', '129.34.123.55' ), 'port' => '3306' ) ); $value = & $this->getFromArray('type.conf.host'); $value = '-- changed ---'; // result $conf = array( 'type' => 'mysql', 'conf' => array( 'name' => 'mydatabase', 'user' => 'root', 'pass' => '12345', 'host' => '-- changed ---' 'port' => '3306' ) ); 

НО, я не могу уничтожить этот раздел:

 // normally success unset($conf['type']['conf']['host']); // fail via reference $value = & $this->getFromArray('type.conf.host'); unset($value); с // normally success unset($conf['type']['conf']['host']); // fail via reference $value = & $this->getFromArray('type.conf.host'); unset($value); 

Есть ли решение?

    Хорошо, лучше я думаю. Чтобы отключиться, вы должны получить ссылку на контейнерный массив, а затем удалить элемент внутри массива;

    т.е.

     $value = & $this->getFromArray('type.conf'); unset $value['host']; 

    Ссылки не похожи на жесткие ссылки. Если вы отключите ссылку, это не приведет к отключению исходного значения.

     <?php $a = 5; xdebug_debug_zval('a'); // a: (refcount=1, is_ref=0), int 5 $b = &$a; xdebug_debug_zval('a'); // a: (refcount=2, is_ref=1), int 5 xdebug_debug_zval('b'); // b: (refcount=2, is_ref=1), int 5 unset($b); xdebug_debug_zval('a'); // a: (refcount=1, is_ref=0), int 5 с <?php $a = 5; xdebug_debug_zval('a'); // a: (refcount=1, is_ref=0), int 5 $b = &$a; xdebug_debug_zval('a'); // a: (refcount=2, is_ref=1), int 5 xdebug_debug_zval('b'); // b: (refcount=2, is_ref=1), int 5 unset($b); xdebug_debug_zval('a'); // a: (refcount=1, is_ref=0), int 5 

    Почему бы не написать небольшой класс Config который абстрагирует данные (массив)? Поскольку объекты всегда передаются по ссылке, вам не нужно будет обрабатывать это самостоятельно.

     class Config { // ... } $config = new Config(array( 'db' => array( 'name' => 'mydatabase', 'user' => 'root', 'pass' => '12345', ) )); $config->get('db.user'); $config->set('db.user', 'newuser'); $config->unset('db.user'); //... 

    Создавая некоторые функции для моей структуры, думайте, что они вас останавливают.

    1. Значение набора функций в массиве с использованием ссылки для навигации
    – если ссылка заканчивается по имени / ключу, это имя / ключ будет равным заданному значению
    – если ссылка заканчивается разделителем, фамилия / ключ будет массивом с заданным значением

     function array_reference_set($input_arr=array(),$reference='',$delimiter='->',$set_var=''){ switch ($reference){ case (is_string($reference)): $reference = array_reverse(explode($delimiter, $reference),true); break; case (!is_array($reference)): return $input_arr; } $key = array_pop($reference); if (count($reference)<1){ if($key!=''){ $input_arr[$key] = $set_var; }elseif (!is_array($input_arr) && $key==''){ $input_arr = array($set_var); }elseif ($key==''){ $input_arr[] = $set_var; } }else{ if (!is_array($input_arr)){ $input_arr = array($key=>array()); } if (isset($input_arr[$key])){ $input_arr[$key] = $this->array_reference_set($input_arr[$key],$reference,$delimiter,$set_var); }else{ $input_arr[$key] = $this->array_reference_set(array(),$reference,$delimiter,$set_var); } } return $input_arr; } $arr = array_reference_set(array(),'a->b->c','->','test'); //equal $arr = array('a'=>array('b'=>array('c'=>'test')));//or $arr['a']['b']['c'] = 'test'; $arr = array_reference_set(array(),'a->b->c->','->','test'); //equal $arr = array('a'=>array('b'=>array('c'=>array('test'))));//or $arr['a']['b']['c'][] = 'test'; 

    2. Функция set unset value из массива с использованием ссылки

    – если ссылка заканчивается, это разделитель, то будет отменено varible с именем / ключом для разделителя
    – один момент использования этой функции: вам нужен массив обновлений, возвращенный результат функции (в конце примера кода)

     function array_reference_unset($input_arr=array(),$reference='',$delimiter='->'){ switch ($reference){ case (is_string($reference)): $reference = array_reverse(explode($delimiter, $reference),true); break; case (!is_array($reference)): return $input_arr; } $key = array_pop($reference); if (count($reference)<1 && is_string($key)){ if ($key!=''){ unset($input_arr[$key]); }else{ return false; } }else{ if (isset($input_arr[$key])){ $ret = $this->array_reference_unset($input_arr[$key],$reference,$delimiter); if ($ret!==false){ $input_arr[$key] = $ret; }else{ unset ($input_arr[$key]); } } } return $input_arr; } $arr = array('a'=>array('b'=>array('c'=>'test')));// test subject $arr = array_reference_unset($arr,'a->b->c','->');//and $arr = array_reference_unset($arr,'a->b->c->','->'); //equal unset($arr['a']['b']['c']); с function array_reference_unset($input_arr=array(),$reference='',$delimiter='->'){ switch ($reference){ case (is_string($reference)): $reference = array_reverse(explode($delimiter, $reference),true); break; case (!is_array($reference)): return $input_arr; } $key = array_pop($reference); if (count($reference)<1 && is_string($key)){ if ($key!=''){ unset($input_arr[$key]); }else{ return false; } }else{ if (isset($input_arr[$key])){ $ret = $this->array_reference_unset($input_arr[$key],$reference,$delimiter); if ($ret!==false){ $input_arr[$key] = $ret; }else{ unset ($input_arr[$key]); } } } return $input_arr; } $arr = array('a'=>array('b'=>array('c'=>'test')));// test subject $arr = array_reference_unset($arr,'a->b->c','->');//and $arr = array_reference_unset($arr,'a->b->c->','->'); //equal unset($arr['a']['b']['c']); 

    ps извините за мой чистый английский

    Вот моя функция для отключения вложенных ключей

     public function unsetKey(string $dotSeparatedKey) { $keys = explode('.', $dotSeparatedKey); $pointer = &$this->data; $current = false; // just to make code sniffer happy // we traverse all but the last key while (($current = array_shift($keys)) && (count($keys) > 0)) { // if some key is missing all the subkeys will be already unset if (!array_key_exists($current, $pointer)) { // is already unset somewhere along the way return; } // set pointer to new, deeper level // called for all but last key $pointer = &$pointer[$current]; } // handles empty input string if ($current) { // we finally unset what we wanted unset($pointer[$current]); } } с public function unsetKey(string $dotSeparatedKey) { $keys = explode('.', $dotSeparatedKey); $pointer = &$this->data; $current = false; // just to make code sniffer happy // we traverse all but the last key while (($current = array_shift($keys)) && (count($keys) > 0)) { // if some key is missing all the subkeys will be already unset if (!array_key_exists($current, $pointer)) { // is already unset somewhere along the way return; } // set pointer to new, deeper level // called for all but last key $pointer = &$pointer[$current]; } // handles empty input string if ($current) { // we finally unset what we wanted unset($pointer[$current]); } }