除了 丰富的 PHP 数组函数集,Yii 数组助手还提供额外的静态方法,使您可以更有效地处理数组。
从数组、对象或由两者组成的复杂结构中检索值,使用标准 PHP 很重复。您必须首先使用 isset
检查键是否存在,如果存在,您就获取它,否则提供默认值
class User
{
public $name = 'Alex';
}
$array = [
'foo' => [
'bar' => new User(),
]
];
$value = isset($array['foo']['bar']->name) ? $array['foo']['bar']->name : null;
Yii 提供了一种非常方便的方法来做到这一点
$value = ArrayHelper::getValue($array, 'foo.bar.name');
第一个方法参数是我们从中获取值的来源。第二个参数指定如何获取数据。它可以是以下之一
回调应该是以下形式
$fullName = ArrayHelper::getValue($user, function ($user, $defaultValue) {
return $user->firstName . ' ' . $user->lastName;
});
第三个可选参数是默认值,如果未指定,则为 null
。可以按如下方式使用
$username = ArrayHelper::getValue($comment, 'user.username', 'Unknown');
$array = [
'key' => [
'in' => ['k' => 'value']
]
];
ArrayHelper::setValue($array, 'key.in', ['arr' => 'val']);
// the path to write the value in `$array` can be specified as an array
ArrayHelper::setValue($array, ['key', 'in'], ['arr' => 'val']);
结果,$array['key']['in']
的初始值将被新值覆盖
[
'key' => [
'in' => ['arr' => 'val']
]
]
如果路径包含一个不存在的键,它将被创建
// if `$array['key']['in']['arr0']` is not empty, the value will be added to the array
ArrayHelper::setValue($array, 'key.in.arr0.arr1', 'val');
// if you want to completely override the value `$array['key']['in']['arr0']`
ArrayHelper::setValue($array, 'key.in.arr0', ['arr1' => 'val']);
结果将是
[
'key' => [
'in' => [
'k' => 'value',
'arr0' => ['arr1' => 'val']
]
]
]
如果您想获取一个值,然后立即将其从数组中删除,可以使用 remove
方法
$array = ['type' => 'A', 'options' => [1, 2]];
$type = ArrayHelper::remove($array, 'type');
执行代码后,$array
将包含 ['options' => [1, 2]]
,$type
将为 A
。请注意,与 getValue
方法不同,remove
只支持简单的键名。
ArrayHelper::keyExists
的工作原理与 array_key_exists 相同,只是它还支持不区分大小写的键比较。例如,
$data1 = [
'userName' => 'Alex',
];
$data2 = [
'username' => 'Carsten',
];
if (!ArrayHelper::keyExists('username', $data1, false) || !ArrayHelper::keyExists('username', $data2, false)) {
echo "Please provide username.";
}
通常,您需要从数据行或对象的数组中获取一列值。常见的例子是获取 ID 列表。
$array = [
['id' => '123', 'data' => 'abc'],
['id' => '345', 'data' => 'def'],
];
$ids = ArrayHelper::getColumn($array, 'id');
结果将是 ['123', '345']
。
如果需要额外的转换或获取值的逻辑复杂,可以将第二个参数指定为一个匿名函数
$result = ArrayHelper::getColumn($array, function ($element) {
return $element['id'];
});
为了根据指定键索引数组,可以使用 index
方法。输入应为多维数组或对象数组。$key
可以是子数组的键名、对象的属性名或匿名函数,该函数必须返回用作键的值。
$groups
属性是一个键数组,将用于根据指定的键将输入数组分组到一个或多个子数组中。
如果 $key
属性或其在特定元素的值为 null
并且 $groups
未定义,则将丢弃数组元素。否则,如果指定了 $groups
,则数组元素将被添加到结果数组中,不带任何键。
例如
$array = [
['id' => '123', 'data' => 'abc', 'device' => 'laptop'],
['id' => '345', 'data' => 'def', 'device' => 'tablet'],
['id' => '345', 'data' => 'hgi', 'device' => 'smartphone'],
];
$result = ArrayHelper::index($array, 'id');
结果将是一个关联数组,其中键是 id
属性的值
[
'123' => ['id' => '123', 'data' => 'abc', 'device' => 'laptop'],
'345' => ['id' => '345', 'data' => 'hgi', 'device' => 'smartphone']
// The second element of an original array is overwritten by the last element because of the same id
]
作为 $key
传递的匿名函数会产生相同的结果
$result = ArrayHelper::index($array, function ($element) {
return $element['id'];
});
将 id
作为第三个参数传递将按 id
对 $array
进行分组
$result = ArrayHelper::index($array, null, 'id');
结果将是一个多维数组,按 id
在第一级进行分组,在第二级不进行索引
[
'123' => [
['id' => '123', 'data' => 'abc', 'device' => 'laptop']
],
'345' => [ // all elements with this index are present in the result array
['id' => '345', 'data' => 'def', 'device' => 'tablet'],
['id' => '345', 'data' => 'hgi', 'device' => 'smartphone'],
]
]
匿名函数也可以在分组数组中使用
$result = ArrayHelper::index($array, 'data', [function ($element) {
return $element['id'];
}, 'device']);
结果将是一个多维数组,按 id
在第一级进行分组,按 device
在第二级进行分组,按 data
在第三级进行索引
[
'123' => [
'laptop' => [
'abc' => ['id' => '123', 'data' => 'abc', 'device' => 'laptop']
]
],
'345' => [
'tablet' => [
'def' => ['id' => '345', 'data' => 'def', 'device' => 'tablet']
],
'smartphone' => [
'hgi' => ['id' => '345', 'data' => 'hgi', 'device' => 'smartphone']
]
]
]
为了从多维数组或对象数组构建映射(键值对),可以使用 map
方法。$from
和 $to
参数指定键名或属性名以设置映射。可以选择根据分组字段 $group
进一步分组映射。例如,
$array = [
['id' => '123', 'name' => 'aaa', 'class' => 'x'],
['id' => '124', 'name' => 'bbb', 'class' => 'x'],
['id' => '345', 'name' => 'ccc', 'class' => 'y'],
];
$result = ArrayHelper::map($array, 'id', 'name');
// the result is:
// [
// '123' => 'aaa',
// '124' => 'bbb',
// '345' => 'ccc',
// ]
$result = ArrayHelper::map($array, 'id', 'name', 'class');
// the result is:
// [
// 'x' => [
// '123' => 'aaa',
// '124' => 'bbb',
// ],
// 'y' => [
// '345' => 'ccc',
// ],
// ]
multisort
方法帮助根据一个或多个键对对象数组或嵌套数组进行排序。例如,
$data = [
['age' => 30, 'name' => 'Alexander'],
['age' => 30, 'name' => 'Brian'],
['age' => 19, 'name' => 'Barney'],
];
ArrayHelper::multisort($data, ['age', 'name'], [SORT_ASC, SORT_DESC]);
排序后,我们将在 $data
中获得以下内容
[
['age' => 19, 'name' => 'Barney'],
['age' => 30, 'name' => 'Brian'],
['age' => 30, 'name' => 'Alexander'],
];
指定要按其排序的键的第二个参数,如果它是一个单个键,可以是字符串;如果它是多个键,可以是数组;或者可以是以下匿名函数
ArrayHelper::multisort($data, function($item) {
// sort by age if it exists or by name otherwise
return isset($item['age']) ? $item['age'] : $item['name'];
});
第三个参数是方向。在按单个键排序的情况下,可以是 SORT_ASC
或 SORT_DESC
。如果按多个值排序,可以提供一个排序方向数组来以不同的方式对每个值进行排序。
最后一个参数是 PHP 排序标志,它可以接受与传递给 PHP sort() 相同的值。
了解数组是索引还是关联数组非常方便。以下是一个示例
// no keys specified
$indexed = ['Qiang', 'Paul'];
echo ArrayHelper::isIndexed($indexed);
// all keys are strings
$associative = ['framework' => 'Yii', 'version' => '2.0'];
echo ArrayHelper::isAssociative($associative);
为了将字符串数组中的特殊字符编码或解码为 HTML 实体,可以使用以下方法
$encoded = ArrayHelper::htmlEncode($data);
$decoded = ArrayHelper::htmlDecode($data);
默认情况下,只有值会被编码。将第二个参数作为 false
传递,也可以对数组的键进行编码。编码将使用应用程序字符集,可以通过第三个参数进行更改。
您可以使用 ArrayHelper::merge() 将两个或多个数组递归地合并为一个。如果每个数组都有一个具有相同字符串键值的元素,则后者将覆盖前者(与 array_merge_recursive() 不同)。如果两个数组都具有数组类型的元素并且具有相同的键,则将进行递归合并。对于整数键元素,来自后一个数组的元素将被追加到前一个数组。您可以使用 yii\helpers\UnsetArrayValue 对象从之前的数组中取消设置值,或者使用 yii\helpers\ReplaceArrayValue 强制替换之前的值,而不是递归合并。
例如
$array1 = [
'name' => 'Yii',
'version' => '1.1',
'ids' => [
1,
],
'validDomains' => [
'example.com',
'www.example.com',
],
'emails' => [
'admin' => '[email protected]',
'dev' => '[email protected]',
],
];
$array2 = [
'version' => '2.0',
'ids' => [
2,
],
'validDomains' => new \yii\helpers\ReplaceArrayValue([
'yiiframework.com',
'www.yiiframework.com',
]),
'emails' => [
'dev' => new \yii\helpers\UnsetArrayValue(),
],
];
$result = ArrayHelper::merge($array1, $array2);
结果将是
[
'name' => 'Yii',
'version' => '2.0',
'ids' => [
1,
2,
],
'validDomains' => [
'yiiframework.com',
'www.yiiframework.com',
],
'emails' => [
'admin' => '[email protected]',
],
]
通常您需要将对象或对象数组转换为数组。最常见的情况是转换活动记录模型,以便通过 REST API 提供数据数组或以其他方式使用它。以下代码可用于执行此操作
$posts = Post::find()->limit(10)->all();
$data = ArrayHelper::toArray($posts, [
'app\models\Post' => [
'id',
'title',
// the key name in array result => property name
'createTime' => 'created_at',
// the key name in array result => anonymous function
'length' => function ($post) {
return strlen($post->content);
},
],
]);
第一个参数包含我们要转换的数据。在本例中,我们正在转换 Post
AR 模型。
第二个参数是每个类的转换映射。我们正在为 Post
模型设置映射。每个映射数组包含一组映射。每个映射可以是
上述转换结果(对于单个模型)将是
[
'id' => 123,
'title' => 'test',
'createTime' => '2013-01-01 12:00AM',
'length' => 301,
]
可以通过在该类中实现 Arrayable 接口,为特定类提供将对象转换为数组的默认方式。
您经常需要检查元素是否在数组中或元素集是否是另一个元素集的子集。虽然 PHP 提供了 in_array()
,但它不支持子集或 \Traversable
对象。
为了帮助进行这些测试,yii\helpers\ArrayHelper 提供了 isIn() 和 isSubset(),它们具有与 in_array() 相同的签名。
// true
ArrayHelper::isIn('a', ['a']);
// true
ArrayHelper::isIn('a', new ArrayObject(['a']));
// true
ArrayHelper::isSubset(new ArrayObject(['a', 'c']), new ArrayObject(['a', 'b', 'c']));
发现错别字或您认为此页面需要改进?
在 github 上编辑 !
注册 或 登录 以发表评论。