# 数组助手类
除了[PHP中丰富的数组函数集](http://php.net/manual/zh/book.array.php), Yii 数组助手类提供了额外的静态方法,让你更高效地处理数组。
## 获取值
用原生PHP从一个对象、数组、或者包含这两者的一个复杂数据结构中获取数据是非常繁琐的。 你首先得使用`isset` 检查 key 是否存在, 然后如果存在你就获取它,如果不存在, 则提供一个默认返回值:
~~~
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');
~~~
对于取到值后想要立即从数组中删除的情况,你可以使用 `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](http://php.net/manual/en/function.array-key-exists.php)差不多,除了 它还可支持大小写不敏感的键名比较,比如:
~~~
$data1 = [
'userName' => 'Alex',
];
$data2 = [
'username' => 'Carsten',
];
if (!ArrayHelper::keyExists('username', $data1, false) || !ArrayHelper::keyExists('username', $data2, false)) {
echo "Please provide username.";
}
~~~
## 检索列
通常你要从多行数据或者多个对象构成的数组中获取某列的值,一个普通的例子是获取id值列表。
~~~
$data = [
['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` 方法。输入的数组应该是多维数组或者是一个对象数组。 键名(译者注:第二个参数)可以是子数组的键名、对象的属性名, 也可以是一个返回给定元素数组键值的匿名函数。
如果一个键值(译者注:第二个参数对应的值)是 null,相应的数组元素将被丢弃并且不会放入到结果中,例如,
~~~
$array = [
['id' => '123', 'data' => 'abc'],
['id' => '345', 'data' => 'def'],
];
$result = ArrayHelper::index($array, 'id');
// the result is:
// [
// '123' => ['id' => '123', 'data' => 'abc'],
// '345' => ['id' => '345', 'data' => 'def'],
// ]
// using anonymous function
$result = ArrayHelper::index($array, function ($element) {
return $element['id'];
});
~~~
## 建立哈希表
为了从一个多维数组或者一个对象数组中建立一个映射表(键值对),你可以使用 `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');
// 结果是:
// [
// '123' => 'aaa',
// '124' => 'bbb',
// '345' => 'ccc',
// ]
$result = ArrayHelper::map($array, 'id', 'name', 'class');
// 结果是:
// [
// '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) {
return isset($item['age']) ? ['age', 'name'] : 'name';
});
~~~
第三个参数表示增降顺序。单键排序时,它可以是 `SORT_ASC` 或者 `SORT_DESC` 之一。 如果是按多个键名排序,你可以用一个数组为各个键指定不同的顺序。
最后一个参数(译者注:第四个参数)是PHP的排序标识(sort flag),可使用的值和调用PHP [sort()](http://php.net/manual/zh/function.sort.php) 函数时传递的值一样。
## 检测数组类型
想知道一个数组是索引数组还是联合数组很方便,这有个例子:
~~~
// 不指定键名的数组
$indexed = ['Qiang', 'Paul'];
echo ArrayHelper::isIndexed($indexed);
// 所有键名都是字符串
$associative = ['framework' => 'Yii', 'version' => '2.0'];
echo ArrayHelper::isAssociative($associative);
~~~
## HTML 编码和解码值
为了将字符串数组中的特殊字符做 HTML 编解码,你可以使用下列方法:
~~~
$encoded = ArrayHelper::htmlEncode($data);
$decoded = ArrayHelper::htmlDecode($data);
~~~
默认情况只会对值做编码(译者注:原文中是编码,应为编解码)。通过给第二个参数传 `false` ,你也可以对键名做编码。 编码将默认使用应用程序的字符集,你可以通过第三个参数指定该字符集。
## 合并数组
~~~
/**
* 将两个或者多个数组递归式的合并为一个数组。
* 如果每个数组有一个元素的键名相同,
* 那么后面元素的将覆盖前面的元素(不同于 array_merge_recursive)。
* 如果两个数组都有相同键名的数组元素(译者注:嵌套数组)
* 则将引发递归合并。
* 对数值型键名的元素,后面数组中的这些元素会被追加到前面数组中。
* @param array $a 被合并的数组
* @param array $b 合并的数组,你可以在第三、第四个
* 参数中指定另外的合并数组,等等
* @return 合并的结果数组 (原始数组不会被改变)
*/
public static function merge($a, $b)
~~~
## 对象转换为数组
你经常要将一个对象或者对象的数组转换成一个数组,常见的情形是,为了通过REST API提供数据数组(或其他使用方式), 将AR模型(活动记录模型)转换成数组。如下代码可完成这个工作:
~~~
$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,
]
~~~
也可以在一个特定的类中实现yii\base\Arrayable接口, 从而为其对象提供默认的转换成数组的方法。
- 介绍(Introduction)
- 关于 Yii(About Yii)
- 从 Yii 1.1 升级(Upgrading from Version 1.1)
- 入门(Getting Started)
- 安装 Yii(Installing Yii)
- 运行应用(Running Applications)
- 第一次问候(Saying Hello)
- 使用 Forms(Working with Forms)
- 玩转 Databases(Working with Databases)
- 用 Gii 生成代码(Generating Code with Gii)
- 更上一层楼(Looking Ahead)
- 应用结构(Application Structure)
- 结构概述(Overview)
- 入口脚本(Entry Scripts)
- 应用(Applications)
- 应用组件(Application Components)
- 控制器(Controllers)
- 模型(Models)
- 视图(Views)
- 模块(Modules)
- 过滤器(Filters)
- 小部件(Widgets)
- 前端资源(Assets)
- 扩展(Extensions)
- 请求处理(Handling Requests)
- 运行概述(Overview)
- 引导(Bootstrapping)
- 路由引导与创建 URL(Routing and URL Creation)
- 请求(Requests)
- 响应(Responses)
- Sessions and Cookies
- 错误处理(Handling Errors)
- 日志(Logging)
- 关键概念(Key Concepts)
- 组件(Components)
- 属性(Properties)
- 事件(Events)
- 行为(Behaviors)
- 配置(Configurations)
- 别名(Aliases)
- 类自动加载(Class Autoloading)
- 服务定位器(Service Locator)
- 依赖注入容器(Dependency Injection Container)
- 配合数据库工作(Working with Databases)
- 数据库访问(Data Access Objects): 数据库连接、基本查询、事务和模式操作
- 查询生成器(Query Builder): 使用简单抽象层查询数据库
- 活动记录(Active Record): 活动记录对象关系映射(ORM),检索和操作记录、定义关联关系
- 数据库迁移(Migrations): 在团体开发中对你的数据库使用版本控制
- Sphinx
- Redis
- MongoDB
- ElasticSearch
- 接收用户数据(Getting Data from Users)
- 创建表单(Creating Forms)
- 输入验证(Validating Input)
- 文件上传(Uploading Files)
- 收集列表输入(Collecting Tabular Input)
- 多模型同时输入(Getting Data for Multiple Models)
- 显示数据(Displaying Data)
- 格式化输出数据(Data Formatting)
- 分页(Pagination)
- 排序(Sorting)
- 数据提供器(Data Providers)
- 数据小部件(Data Widgets)
- 操作客户端脚本(Working with Client Scripts)
- 主题(Theming)
- 安全(Security)
- 认证(Authentication)
- 授权(Authorization)
- 处理密码(Working with Passwords)
- 客户端认证(Auth Clients)
- 安全领域的最佳实践(Best Practices)
- 缓存(Caching)
- 概述(Overview)
- 数据缓存(Data Caching)
- 片段缓存(Fragment Caching)
- 分页缓存(Page Caching)
- HTTP 缓存(HTTP Caching)
- RESTful Web 服务
- 快速入门(Quick Start)
- 资源(Resources)
- 控制器(Controllers)
- 路由(Routing)
- 格式化响应(Response Formatting)
- 授权验证(Authentication)
- 速率限制(Rate Limiting)
- 版本化(Versioning)
- 错误处理(Error Handling)
- 开发工具(Development Tools)
- 调试工具栏和调试器(Debug Toolbar and Debugger)
- 使用 Gii 生成代码(Generating Code using Gii)
- TBD 生成 API 文档(Generating API Documentation)
- 测试(Testing)
- 概述(Overview)
- 搭建测试环境(Testing environment setup)
- 单元测试(Unit Tests)
- 功能测试(Functional Tests)
- 验收测试(Acceptance Tests)
- 测试夹具(Fixtures)
- 高级专题(Special Topics)
- 高级应用模版(Advanced Project Template)
- 从头构建自定义模版(Building Application from Scratch)
- 控制台命令(Console Commands)
- 核心验证器(Core Validators)
- 国际化(Internationalization)
- 收发邮件(Mailing)
- 性能优化(Performance Tuning)
- 共享主机环境(Shared Hosting Environment)
- 模板引擎(Template Engines)
- 集成第三方代码(Working with Third-Party Code)
- 小部件(Widgets)
- Bootstrap 小部件(Bootstrap Widgets)
- jQuery UI 小部件(jQuery UI Widgets)
- 助手类(Helpers)
- 助手一览(Overview)
- Array 助手(ArrayHelper)
- Html 助手(Html)
- Url 助手(Url)