jausions / php-typed-collections
具有类型约束的集合和数组。
v1.0.0
2018-03-08 20:02 UTC
Requires
- php: ^7.1
Requires (Dev)
- fzaninotto/faker: ^v1.7.1
- phpunit/phpunit: ^7.0.2
This package is not auto-updated.
Last update: 2024-09-29 23:40:55 UTC
README
类型提示正在演变,但PHP 7目前还没有提供定义数组元素类型的方法。
此库提供了一些特质,可用于实现类型检查。
如果您不想实现任何内容,只需使用以下预构建解决方案之一
- 对于Doctrine集合,请参阅此包:jausions/php-typed-doctrine-collections。
对于此库的目的,术语“类型”被宽泛地用来指代内置PHP类型、类,甚至是应用域类型。
安装
composer require jausions/php-typed-collections
以下示例中隐含了require 'vendor/autoload.php';。
简单示例
此示例仅实现了ArrayAccess PHP预定义接口。这意味着没有foreach迭代、count()等...
<?php use Abacus11\Collections\{ TypedCollection, TypedArrayAccessTrait }; class ArrayOf implements \ArrayAccess, TypedCollection { use TypedArrayAccessTrait; }
由样本值定义的类型
元素验证是对样本值的类型进行的。
<?php // With the ArrayOf class defined above $sample = 1; $int_array = (new ArrayOf())->setElementTypeLike($sample); $int_array[] = 2; // Okay $int_array[] = true; // Not okay - throws \TypeError exception class SomeClass {} $sample = new SomeClass(); $some = (new ArrayOf())->setElementTypeLike($sample); $some[] = new SomeClass(); // Okay $some[] = new stdClass(); // Not okay - throws \TypeError exception
由闭包定义的类型
可以闭包来检查添加到集合中的元素。
<?php // With the ArrayOf class defined above $positive_int = (new ArrayOf())->setElementType(function ($value) { if (!is_integer($value)) { return false; } return ($value >= 0); }); $positive_int['apples'] = 0; // Okay $positive_int['oranges'] = 10; // Okay $positive_int['bananas'] = -5; // Not okay - throws a \TypeError exception
由类名定义的类型
添加到集合中的对象可以与类名进行比较。
<?php // With the ArrayOf class defined above class A {} class B {} class AA extends A {} $some_a = (new ArrayOf())->setElementType(A::class); $some_a[] = new A(); // Okay $some_a[] = new AA(); // Okay $some_a[] = new B(); // Not okay - throws \TypeError exception
内置库类型
除了闭包或类名外,setElementType()方法还接受以下预定义值
数组布尔值可调用双精度浮点数整数数字JSON对象资源字符串
<?php // With the ArrayOf class defined above $int_array = (new ArrayOf())->setElementType('integer'); $int_array[] = 1; // Okay $int_array[] = '1'; // Not okay - throws \TypeError exception
检查值
如果您想知道一个值是否会被接受到类型集合中,可以使用isElementType()方法。
<?php // With the ArrayOf class defined above $collection = (new ArrayOf())->setElementType('integer'); $value = 'abc'; if ($collection->isElementType($value)) { // Do something }
自定义类型集合
您可以通过扩展基类或包含特质到您自己的ArrayAccess接口实现中轻松创建集合。
<?php class Vehicle { } class Car extends Vehicle { public $make; public $model; public $color; public $license_plate_number; } class Submarine extends Vehicle { public $name; } // With the ArrayOf class defined above class Cars extends ArrayOf { public function __construct() { $this->setElementType(Car::class); } } class Parking { /** * @var Cars */ protected $lot; public function __construct() { $this->lot = new Cars(); } public function enter(Vehicle $car) { $this->lot[] = $car; } /** * @return Car[] The collection of cars */ public function getCars(): Cars { return $this->lot; } //... } $my_car = new Car(); $my_car->model = 'T'; $my_car->make = 'Ford'; $my_car->color = 'Black'; $my_car->license_plate_number = 'MI-01234'; $my_sub = new Submarine(); $my_sub->name = 'Nautilus'; $parking = new Parking(); $parking->enter($my_car); // Okay $parking->enter($my_sub); // Not okay - throws \TypeError exception
备注
- 我们本可以用
Car类而不是Vehicle类来提示enter()方法。这也会抛出\TypeError异常。 - 我知道我在docBlock和
getCars()方法的签名中混合了类型。这可能会更易于阅读,也可能有助于您的IDE。然而,效果可能因编辑器/IDE而异,并且如果尝试使用一些期望原生array类型的数组函数,可能会导致混淆。