jtl/php-generic-collection

PHP通用的集合实现


README

Build status

使用迭代器在PHP中实现通用集合。无需使用技巧或糟糕的代码即可为您的数组带来类型安全性。

用法

使用此库的主要方式是创建自己的集合类,该类扩展了GenericCollection并在构造函数中设置其类型,如下所示

use JTL\Generic\GenericCollection;

class MyItemCollection extends GenericCollection {
    public function __construct()
    {
        parent::__construct(MyItem::class);
    }
}

您现在可以使用$collection[] = ...或使用静态from函数批量向您的集合中添加新项目。

$collection = new MyItemCollection();
$item1 = new MyItem(1);
$item2 = new MyItem(2);
$item3 = new MyItem(3);
$itemList = [
    $item1,
    $item2,
    $item3
];

$collection[] = $item1;
$collection->addItemList([$item2, $item3]);

$collection2 = MyItemCollection::from($item1, $item2, $item3);
$collection3 = MyItemCollection::from(...$itemList);

或者,您可以直接使用通用的ObjectCollection,而不需要为每种对象类型创建新的集合类。

$collection = new ObjectCollection(MyItem::class);
$item1 = new MyItem(1);
$item2 = new MyItem(2);
$item3 = new MyItem(3);
$itemList = [
    $item1,
    $item2,
    $item3
];

$collection[] = $item1;
$collection->addItemList([$item2, $item3]);

$collection2 = ObjectCollection::from($item1, $item2, $item3);
$collection3 = ObjectCollection::from(...$itemList);

尝试添加不符合指定类型的新项目将抛出InvalidArgumentException

$collection = new ObjectCollection(MyItem::class);
$item1 = new MyItem(1);
$item2 = 'not MyItem';
$item3 = new MyItem(3);

$collection[] = $item1;
$collection[] = $item2; // <- Doesn't work. This will throw an exception + PHPStan will report the error
$collection->addItemList([$item2, $item3]); // <- This won't work either because $item2 is not a 'MyItem'

高级类型检查

默认类型检查函数仅检查要添加的项目是否是给定类型的实例,或者如果将类型设置为“字符串”,则是否是字符串。
如果您需要更高级的类型检查,可以轻松实现自己的算法。
您的自定义集合类只需重写checkType方法,并在类型匹配时返回true,不匹配时返回false

以下是一个仅接受偶数的集合示例。

use JTL\Generic\GenericCollection;

class EvenCollection extends GenericCollection {
    public function checkType($item): bool {
        return $item % 2 === 0;
    }
}

$e = new EvenCollection();
$e[] = 2;
$e[] = 4;
$e[] = 5; // <- Doesn't work. This will throw an exception

迭代器方法

除了确保类型安全性外,GenericCollection还实现了一些方法,使使用迭代器更加愉快。
注意:其中一些方法会修改集合的状态。如果不希望这种行为,请在修改之前对集合进行clone

目前实现了以下方法

什么是压缩(zipping)?

压缩将两个集合连接起来,使得新集合的每个元素都是来自第一个(或左侧)集合和一个来自第二个(或右侧)集合的元素的元组。为了保持代码的可读性,您可以使用getLeft()getRight()访问元组的元素。

示例

$itemList1 = new ItemCollection();
$itemList2 = new ItemCollection();
 
$item11 = new Item('123');
$item12 = new Item('789');
 
$item21 = new Item('456');
$item22 = new Item('0');
 
$itemList1[] = $item11;
$itemList1[] = $item12;
 
$itemList2[] = $item21;
$itemList2[] = $item21;
 
$zip = $itemList1->zip($itemList2);
 
foreach ($zip as $tuple) {
    echo $tuple->getLeft()->getContent() . $tuple->getRight()->getContent() . "\n";
}
 
// Output:
123456
7890

重要!您可以压缩不同类型的两个集合!

解压缩(Unzipping)

可以使用压缩集合上的unzip()方法将压缩集合解压缩为两个原始集合。

基于前面的示例

[$unzippedItemList1, $unzippedItemList2] = $zip->unzip();

此时$itemList1$unzippedItemList1将是相同的。对于$itemList2$unzippedItemList2也是一样。

压缩集合在内部存储原始集合类型,因此即使您压缩了两种不同的集合类型,解压缩也是可能的。

许可

代码在MIT许可证下发布。