目的とする関数
パフォーマンス面はおいといて,利便性の面からこんな関数が欲しい.できればeval
は使いたくない.
<?php
$array = [
'a' => [
'b' => [
'c' => 1,
],
],
];
var_dump(array_get($array, 'a.b')); // ['c' => 1]
var_dump(array_get($array, 'a.b.c')); // int(1)
var_dump(array_get($array, 'a.b.x')); // NULL
array_set($array, 'a.b.d', 2);
var_dump(array_get($array, 'a.b')); // ['c' => 1, 'd' => 2]
array_unset($array, 'a.b.c');
var_dump(array_get($array, 'a.b')); // ['d' => 2]
array_unset($array, 'a.x');
var_dump(array_get($array, 'a')); // ['b' => ['d' => 2]]
array_unset($array, 'a');
var_dump($array); // []
実装
array_unset
だけちょっと複雑になってます.
- 要素を削除するためには必ず親が必要なので
$current
を辿りつつ$parent
も同時にずらしていく - 存在しない要素を参照代入で作ってしまわないように
array_key_exists
でのチェックが必要
<?php
function array_get(array $array, $path, $separator = '.') {
$keys = explode($separator, $path);
$current = $array;
foreach ($keys as $key) {
if (!isset($current[$key])) return;
$current = $current[$key];
}
return $current;
}
function array_set(array &$array, $path, $value, $separator = '.') {
$keys = explode($separator, $path);
$current = &$array;
foreach ($keys as $key) {
$current = &$current[$key];
}
$current = $value;
}
function array_unset(array &$array, $path, $separator = '.') {
$keys = explode($separator, $path);
$current = &$array;
$parent = &$array;
foreach ($keys as $i => $key) {
if (!array_key_exists($key, $current)) return;
if ($i) $parent = &$current;
$current = &$current[$key];
}
unset($parent[$key]);
}