star/collection

集合工具库

1.3.0 2014-12-15 05:52 UTC

README

主分支: 构建状态

开发: 构建状态

提供多种集合实现的库。

安装

要使用 [composer] (https://getcomposer.org.cn/) 安装此包,您只需将以下行添加到您的 composer.json 文件中。

...
"require": {
    "star/collection": "~1.2"
}
...

支持的集合

枚举

将不可变值数组包装在对象中。确保传递给枚举的任何值都由实例支持。

$enumeration = new Enumeration(array(1,2,3));
$enumeration->getSelected(); // returns null
$enumeration->select(2);
$enumeration->getSelected(); // returns 2
$enumeration->select('invalid'); // Throw Exception

类型化集合

包装特定类型的对象(类或接口)的集合。如果给定的值不支持集合,则集合将抛出异常。

基本用法

$collection = new TypedCollection('\stdClass');
$collection->add(2); // Throw exception
$collection->add(new \stdClass()); // works

$collection = new TypedCollection('\Countable');
$collection->add(2); // Throw exception
$collection->add(new ClassThatImplementsCountable()); // works

高级用法

使用组合

假设你想有一个 Car 集合,你可以使用基本用法来定义它,但这会导致代码重复。所以一个好的做法是定义一个新的名为 CarCollection 的类,并使用组合而不是继承,并声明如下

class CarCollection
{
    private $collection;

    public function __construct()
    {
        $this->collection = new TypedCollection('tests\Star\Component\Collection\Example\Car');
    }
}

以这种方式声明您的集合将使您能够将相关的逻辑封装在一个地方,而不是冒着暴露内部实现给外部世界的风险。这样,您就可以控制哪些方法可用,并避免重复。

使用此示例,通过实现 addCar 方法,轻松向集合添加 Car

class CarCollection
{
    ...
    public function addCar(Car $car)
    {
        $this->collection->add($car);
    }
    ...
}

同样,如果您想根据颜色过滤所有汽车,您可以在内部使用它如下

class CarCollection
{
    ...
    public function findAllCarWithColor(Color $color)
    {
        $closure = function(Car $car) use ($color) {
            return $car->getColor() == $color;
        };

        return $this->collection->filter($closure)->toArray();
    }
    ...
}

同样,也可以根据名称找到汽车

class CarCollection
{
    ...
    public function findAllWithName($name)
    {
        $expression = Criteria::expr()->eq('name', $name);
        $criteria = new Criteria($expression);

        return $this->collection->matching($criteria)->toArray();
    }
    ...
}

从现在起,您的集合可重用,可在同一位置测试,同时避免继承的陷阱。

使用继承

class PassengerCollection extends TypedCollection
{
    ...
    public function findAllWithName($name)
    {
        $expression = Criteria::expr()->eq('name', $name);
        $criteria = new Criteria($expression);

        return $this->matching($criteria)->toArray();
    }
    ...
}

使用 Doctrine

此类可以与 doctrine/dbal 一起使用作为附加功能,但您需要确保以下步骤得到遵守。

  • 自定义集合应继承自实现 Doctrine\Common\Collections\CollectionTypedCollection

  • 在实体化时,集合属性将被 Doctrine\ORM\PersistentCollection 替换,而不是自定义集合,尽管集合是在构造函数中实例化的。为了绕过此功能,应像这样实现应返回自定义集合的任何方法

    class Entity { // 可由 Doctrine 使用 PersistentCollection 实体化的自定义集合 private $myElements;

      public function __construct()
      {
          $this->myElements = new CustomCollection('stdClass');
      }
    
      public function getElements()
      {
          // At this point $this->myElements could be a Persistent collection
          return new CustomCollection($this->myElements->toArray());
      }
    

    }