php数组规范写法,PHP中数组规范和自定义集合

20200617_5eea2176458b2.jpg

这差不多是一个关于数组设计的风格指南,但是把它添加到对象设计风格指南感觉不太对,因为不是所有的面向对象语言都有动态数组。本文中的示例是用 PHP 编写的,因为 PHP 很像 Java(可能比较熟悉),但是使用的是动态数组而不是内置的集合类和接口。

使用数组作为列表

所有元素都应该具有相同的类型

当使用一个数组作为一个列表(一个具有特定顺序的值的集合)时,每个值应该是 z 类型:

$goodList = [ 'a', 'b' ]; $badList = [ 'a', 1 ];

一个被普遍接受的注释列表类型的风格是:@var array。 确保不添加索引的类型(它总是int)。

应该忽略每个元素的索引

PHP 将自动为列表中的每个元素(0、1、2等)创建新索引。然而,你不应该依赖这些索引,也不应该直接使用它们。客户端应该依赖的列表的唯一属性是可迭代的和可计数的。

因此,可以随意使用foreach和count(),但不要使用for循环遍历列表中的元素:

// 好的循环: foreach ($list as $element) { } // 不好的循环 (公开每个元素的索引): foreach ($list as $index => $element) { } // 也是不好的循环 (不应该使用每个元素的索引): for ($i = 0; $i < count($list); $i++) { }

(在 PHP 中,for循环甚至可能不起作用,因为列表中可能缺少索引,而且索引可能比列表中的元素数量还要多。)

使用过滤器而不是删除元素

你可能希望通过索引从列表中删除元素(unset()),但是,你应该使用array_filter()来创建一个新列表(没有不需要的元素),而不是删除元素。

同样,你不应该依赖于元素的索引,因此,在使用array_filter()时,不应该使用flag 参数去根据索引过滤元素,甚至根据元素和索引过滤元素。

// 好的过滤: array_filter( $list, function (string $element): bool { return strlen($element) > 2; } ); // 不好的过滤器(也使用索引来过滤元素) array_filter( $list, function (int $index): bool { return $index > 3; }, ARRAY_FILTER_USE_KEY ); // 不好的过滤器(同时使用索引和元素来过滤元素) array_filter( $list, function (string $element, int $index): bool { return $index > 3 || $element === 'Include'; }, ARRAY_FILTER_USE_BOTH );

使用数组作为映射

当键是相关的,而不是索引(0,1,2,等等)。你可以随意使用数组作为映射(可以通过其唯一的键从其中检索值)。

所有的键应该是相同的类型

使用数组作为映射的第一个规则是,数组中的所有键都应该具有相同的类型(最常见的是string类型的键)。

$goodMap = [ 'foo' => 'bar', 'bar' => 'baz' ]; // 不好(使用不同类型的键) $badMap = [ 'foo' => 'bar', 1 => 'baz' ];

所有的值都应该是相同的类型

映射中的值也是如此:它们应该具有相同的类型。

$goodMap = [ 'foo' => 'bar', 'bar' => 'baz' ]; // 不好(使用不同类型的值) $badMap = [ 'foo' => 'bar', 'bar' => 1 ];

一种普遍接受的映射类型注释样式是: @var array。

映射应该保持私有

列表可以安全地在对象之间传递,因为它们具有简单的特征。任何客户端都可以使用它来循环其元素,或计数其元素,即使列表是空的。映射则更难处理,因为客户端可能依赖于没有对应值的键。这意味着在一般情况下,它们应该对管理它们的对象保持私有。不允许客户端直接访问内部映射,而是提供 getter (可能还有 setter )来检索值。如果请求的键不存在值,则抛出异常。但是,如果您可以保持映射及其值完全私有,那么就这样做。

// 公开一个列表是可以的 /** * @return array */ public function allUsers(): array { // ... } // 公开地图可能很麻烦 /** * @return array */ public function usersById(): array { // ... } // 相反,提供一种方法来根据其键检索值 /** * @throws UserNotFound */ public function userById(string $id): User { // ... }

对具有多个值类型的映射使用对象

当你想要在一个映射中存储不同类型的值时,请使用一个对象。定义一个类,并向其添加公共的类型化属性,或添加构造函数和 getter。像这样的对象的例子是配置对象,或者命令对象:

final class SillyRegisterUserCommand { public string $username; public string $plainTextPassword; public bool $wantsToReceiveSpam; public int $answerToIAmNotARobotQuestion; }

这些规则的例外

有时,库或框架需要以更动态的方式使用数组。在这些情况下,不可能(也不希望)遵循前面的规则。例如数组数据,它将被存储在一个数据库表中,或者Symfony 表单配置。

自定义集合类

自定义集合类是一种非常酷的方法,最后可以和Iterator、ArrayAccess和其朋友一起使用,但是我发现大多数生成的代码令人很困惑。第一次查看代码的人必须在 PHP 手册中查找详细信息,即使他们是有经验的开发人员。另外,你需要编写

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值