Looking into Kohana documentation, i found this really usefull function that they use to get values from a multidimensional array using a dot notation, for example:
查看Kohana文档,我发现这个非常有用的函数,它们用于使用点表示法从多维数组中获取值,例如:
$foo = array('bar' => array('color' => 'green', 'size' => 'M'));
$value = path($foo, 'bar.color', NULL , '.');
// $value now is 'green'
Im wondering if there is a way to set the an array value in the same way:
我想知道是否有办法以相同的方式设置数组值:
set_value($foo, 'bar.color', 'black');
The only way i found to do that is re-building the array notation ($array['bar']['color']) and then set the value.. using eval
.
我发现这样做的唯一方法是重新构建数组表示法($ array ['bar'] ['color'])然后使用eval设置值。
Any idea to avoid eval?
有什么想避免评估?
6 个解决方案
#1
35
function set_val(array &$arr, $path,$val)
{
$loc = &$arr;
foreach(explode('.', $path) as $step)
{
$loc = &$loc[$step];
}
return $loc = $val;
}
#2
9
Sure it's possible.
当然有可能。
The code
function set_value(&$root, $compositeKey, $value) {
$keys = explode('.', $compositeKey);
while(count($keys) > 1) {
$key = array_shift($keys);
if(!isset($root[$key])) {
$root[$key] = array();
}
$root = &$root[$key];
}
$key = reset($keys);
$root[$key] = $value;
}
How to use it
$foo = array();
set_value($foo, 'bar.color', 'black');
print_r($foo);
Outputs
输出
Array
(
[bar] => Array
(
[color] => black
)
)
看到它在行动。
#3
6
Look at https://gist.github.com/elfet/4713488
请访问https://gist.github.com/elfet/4713488
$dn = new DotNotation(['bar'=>['baz'=>['foo'=>true]]]);
$value = $dn->get('bar.baz.foo'); // $value == true
$dn->set('bar.baz.foo', false); // ['foo'=>false]
$dn->add('bar.baz', ['boo'=>true]); // ['foo'=>false,'boo'=>true]
#4
4
That way you can set the following values more than once to the same variable.
这样,您可以将多个以下值设置为同一个变量。
You can make these two ways (by static variable and reference variable):
您可以通过以下两种方式(通过静态变量和引用变量):
<?php
function static_dot_notation($string, $value)
{
static $return;
$token = strtok($string, '.');
$ref =& $return;
while($token !== false)
{
$ref =& $ref[$token];
$token = strtok('.');
}
$ref = $value;
return $return;
}
$test = static_dot_notation('A.1', 'A ONE');
$test = static_dot_notation('A.2', 'A TWO');
$test = static_dot_notation('B.C1', 'C ONE');
$test = static_dot_notation('B.C2', 'C TWO');
$test = static_dot_notation('B.C.D', 'D ONE');
var_export($test);
/**
array (
'A' =>
array (
1 => 'A ONE',
2 => 'A TWO',
),
'B' =>
array (
'C1' => 'C ONE',
'C2' => 'C TWO',
'C' =>
array (
'D' => 'D ONE',
),
),
*/
function reference_dot_notation($string, $value, &$array)
{
static $return;
$token = strtok($string, '.');
$ref =& $return;
while($token !== false)
{
$ref =& $ref[$token];
$token = strtok('.');
}
$ref = $value;
$array = $return;
}
reference_dot_notation('person.name', 'Wallace', $test2);
reference_dot_notation('person.lastname', 'Maxters', $test2);
var_export($test2);
/**
array (
'person' =>
array (
'name' => 'Wallace',
'lastname' => 'Maxters',
),
)
*/
#5
3
I created a small class just for this!
我为此创建了一个小班级!
http://github.com/projectmeta/Stingray
http://github.com/projectmeta/Stingray
$stingray = new StingRay();
//To Get value
$stingray->get($array, 'this.that.someother'):
//To Set value
$stingray->get($array, 'this.that.someother', $newValue):
#6
0
Updated @hair resins' answer to cater for:
更新了@hair树脂的答案,以满足:
- When a sub-path already exists, or
- 当子路径已经存在时,或
-
When a sub-path is not an array
当子路径不是数组时
function set_val(array &$arr, $path,$val) { $loc = &$arr; $path = explode('.', $path); foreach($path as $step) { if ( ! isset($loc[$step]) OR ! is_array($loc[$step])) $loc = &$loc[$step]; } return $loc = $val; }
#1
35
function set_val(array &$arr, $path,$val)
{
$loc = &$arr;
foreach(explode('.', $path) as $step)
{
$loc = &$loc[$step];
}
return $loc = $val;
}
#2
9
Sure it's possible.
当然有可能。
The code
function set_value(&$root, $compositeKey, $value) {
$keys = explode('.', $compositeKey);
while(count($keys) > 1) {
$key = array_shift($keys);
if(!isset($root[$key])) {
$root[$key] = array();
}
$root = &$root[$key];
}
$key = reset($keys);
$root[$key] = $value;
}
How to use it
$foo = array();
set_value($foo, 'bar.color', 'black');
print_r($foo);
Outputs
输出
Array
(
[bar] => Array
(
[color] => black
)
)
看到它在行动。
#3
6
Look at https://gist.github.com/elfet/4713488
请访问https://gist.github.com/elfet/4713488
$dn = new DotNotation(['bar'=>['baz'=>['foo'=>true]]]);
$value = $dn->get('bar.baz.foo'); // $value == true
$dn->set('bar.baz.foo', false); // ['foo'=>false]
$dn->add('bar.baz', ['boo'=>true]); // ['foo'=>false,'boo'=>true]
#4
4
That way you can set the following values more than once to the same variable.
这样,您可以将多个以下值设置为同一个变量。
You can make these two ways (by static variable and reference variable):
您可以通过以下两种方式(通过静态变量和引用变量):
<?php
function static_dot_notation($string, $value)
{
static $return;
$token = strtok($string, '.');
$ref =& $return;
while($token !== false)
{
$ref =& $ref[$token];
$token = strtok('.');
}
$ref = $value;
return $return;
}
$test = static_dot_notation('A.1', 'A ONE');
$test = static_dot_notation('A.2', 'A TWO');
$test = static_dot_notation('B.C1', 'C ONE');
$test = static_dot_notation('B.C2', 'C TWO');
$test = static_dot_notation('B.C.D', 'D ONE');
var_export($test);
/**
array (
'A' =>
array (
1 => 'A ONE',
2 => 'A TWO',
),
'B' =>
array (
'C1' => 'C ONE',
'C2' => 'C TWO',
'C' =>
array (
'D' => 'D ONE',
),
),
*/
function reference_dot_notation($string, $value, &$array)
{
static $return;
$token = strtok($string, '.');
$ref =& $return;
while($token !== false)
{
$ref =& $ref[$token];
$token = strtok('.');
}
$ref = $value;
$array = $return;
}
reference_dot_notation('person.name', 'Wallace', $test2);
reference_dot_notation('person.lastname', 'Maxters', $test2);
var_export($test2);
/**
array (
'person' =>
array (
'name' => 'Wallace',
'lastname' => 'Maxters',
),
)
*/
#5
3
I created a small class just for this!
我为此创建了一个小班级!
http://github.com/projectmeta/Stingray
http://github.com/projectmeta/Stingray
$stingray = new StingRay();
//To Get value
$stingray->get($array, 'this.that.someother'):
//To Set value
$stingray->get($array, 'this.that.someother', $newValue):
#6
0
Updated @hair resins' answer to cater for:
更新了@hair树脂的答案,以满足:
- When a sub-path already exists, or
- 当子路径已经存在时,或
-
When a sub-path is not an array
当子路径不是数组时
function set_val(array &$arr, $path,$val) { $loc = &$arr; $path = explode('.', $path); foreach($path as $step) { if ( ! isset($loc[$step]) OR ! is_array($loc[$step])) $loc = &$loc[$step]; } return $loc = $val; }