jausions/php-typed-collections

具有类型约束的集合和数组。

v1.0.0 2018-03-08 20:02 UTC

This package is not auto-updated.

Last update: 2024-09-29 23:40:55 UTC


README

类型提示正在演变,但PHP 7目前还没有提供定义数组元素类型的方法。

此库提供了一些特质,可用于实现类型检查。

如果您不想实现任何内容,只需使用以下预构建解决方案之一

对于此库的目的,术语“类型”被宽泛地用来指代内置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

备注

  1. 我们本可以用Car类而不是Vehicle类来提示enter()方法。这也会抛出\TypeError异常。
  2. 我知道我在docBlockgetCars()方法的签名中混合了类型。这可能会更易于阅读,也可能有助于您的IDE。然而,效果可能因编辑器/IDE而异,并且如果尝试使用一些期望原生array类型的数组函数,可能会导致混淆。