fusion-php/collection

适用于PHP 7.4+的小型集合库

3.0.0 2021-02-10 11:00 UTC

This package is auto-updated.

Last update: 2024-09-10 18:54:14 UTC


README

Scrutinizer Code Quality Code Coverage Build Status

本包提供一个小型集合库,适用于在对象中聚合数据值。存储的值可以通过方法、循环或数组访问。

需求

PHP 7.4或更高版本。

安装

此包通过Composer安装。

composer require fusion-php/collection

用法

该库提供了两种不同类型的集合。基本对象,简单地称为Collection,以及Dictionary。这两种类型有两个变体,称为TypedCollectionTypedDictionary,用于存储特定对象类型的实例。

实例化

可以通过构造函数或使用CollectionFactory类创建本库提供的任何集合对象。本节以下内容将假设使用CollectionFactory类创建集合对象。有关构造函数实例化的信息,请参阅以下手动实例化部分。

集合类

Collection对象将保留PHP数组可以保留的任何值,除了null值。

Collection可以实例化为空或包含起始元素的数组。在后一种情况下,现有数组的键将被忽略。

<?php

namespace App;

use Fusion\Collection\CollectionFactory;

require '../vendor/autoload.php';

$collection = CollectionFactory::newCollection(); //empty

// ... or ...

$items = ['foo', 'bar', 'baz'];    
$collection = CollectionFactory::newCollection($items);

var_dump($collection->count()); //int (3)

如上所示,count()方法返回一个整数,表示集合中的项目数。集合使用Countable接口,允许您通过PHP的count()方法以另一种方式获取集合大小。

$size = count($collection); //same as $size = $collection->count();

要向集合添加项目,请使用add()方法并传递您希望存储的值。

$collection->add(42);

使用带有现有索引的find()方法从集合中检索值。

$collection = CollectionFactory::newCollection(['foo', 'bar', 'baz']);
var_dump($collection->find(1)); //string 'bar'

可以通过调用replace()方法并传递要替换的值的索引和替换值来替换集合中的值。

$collection = CollectionFactory::newCollection(['foo', 'bar', 'baz']);
$collection->replace(1, 'bam'); //Collection is now ['foo', 'bam', 'baz']

要从不集合中删除项目,请使用remove()方法并传递要删除的值。

$collection = CollectionFactory::newCollection(['foo', 'bar', 'baz']);
$collection->remove('foo'); //count() == 2

使用remove()方法将删除所有与提供的参数相同的值。这意味着也会删除任何相同实例的重复值或对象的重复值。要删除特定值,请使用removeAt()方法并传递值的数值索引。

$collection = CollectionFactory::newCollection(['foo', 'bar', 'baz']);
$collection->removeAt(1); //Collection is now [0 => 'foo', 1 => 'baz');

remove()removeAt()方法都会导致集合的数值索引更新,关闭索引序列中的任何间隙。

要清空集合,只需调用clear()方法。

$collection = CollectionFactory::newCollection(['foo', 'bar', 'baz']);
$collection->clear();
var_dump($collection->count()); //int (0)

迭代和直接访问

Collection实例可以使用ArrayAccessIterator。这意味着您可以使用集合作为forforeach的主体。

$collection = CollectionFactory::newCollection(['foo', 'bar', 'baz']);

for ($i = 0; $i < count($collection); $i++)
{
    //... do something with $collection[$i];
}

// ... or ...

foreach ($collection as $key => $value)
{
    //... do something with $key and/or $value
}

如果您可以直接通过它们的索引访问和替换项目,那么您也可以这样做。

$collection = CollectionFactory::newCollection(['foo', 'bar', 'baz']);

var_dump($collection[2]); //string 'baz'
$collection[2] = 'qux'; //same as calling $collection->replace(2, 'qux');

您可以随时通过带有值索引的unset()调用以这种方式删除项目。

unset($collection[3]); //same as calling $collection->removeAt(3);

字典类

DictionaryCollection非常相似,主要区别在于Dictionary只接受字符串索引(以下简称键)。Dictionary将保留PHP数组可以保留的任何值,除了null值。

字典可以被实例化为空字典或包含起始元素的数组。在后一种情况下,数组中存在的键不会被忽略,但它们必须是字符串。

<?php

namespace App;

use Fusion\Collection\CollectionFactory;

require '../vendor/autoload.php';

$dictionary = CollectionFactory::newDictionary(); //empty

// ... or ...

$items = ['foo' => 'bar', 'baz' => 'bam'];    
$dictionary = CollectionFactory::newDictionary($items);

var_dump($dictionary->count()); //int (2)

如上所示,可以使用 count() 方法获取字典中的项目数量,并且,与 Collection 类一样,也可以使用 PHP 的 count() 方法来获取。

$size = count($dictionary); //same as $size = $dictionary->count();

可以使用 add() 方法将项目添加到字典中,指定存储它们的键。

$dictionary->add('foo', 'bar');

也可以在给定的键处替换项目。

$dictionary->replace('foo', 'bam');

Dictionary 类中的 find()remove()removeAt()clear() 方法的工作方式与在 Collection 类中完全相同,其中 find()removeAt() 方法需要它们的参数是字符串而不是整数。

迭代和直接访问

Dictionary 类还利用了 ArrayAccessIterator 接口,允许循环遍历。

$dictionary = CollectionFactory::newDictionary(['foo1' => 'bar', 'foo2' => 'bam']);

for ($i = 1; $i <= count($dictionary); $i++)
{
    // ... do something with $dictionary['foo' . $i];
}

// ... or ...

foreach ($dictionary as $key => $value)
{
    // ... do something with $key and/or $value
}

可以通过键偏移直接访问字典中的值。

$dictionary = CollectionFactory::newDictionary(['foo' => 'bar', 'baz' => 'bam']);
var_dump($dictionary['baz']); //string 'bam'

可以直接使用 unset() 移除项目。

unset($dictionary['foo']); // same as calling $dictionary->removeAt('foo');

可以直接在它们的偏移处替换值,并且还可以直接在它们的偏移处添加新项目。

$dictionary['foo'] = 'bar'; 
// same as calling $dictionary->add('foo', 'bar'); or $dictionary->replace('foo', 'bar');

TypedCollection 和 TypedDictionary 类

在某些情况下,可能需要有一个只存储特定类型对象引用的集合或字典。在这些情况下,可以使用 TypedCollectionTypedDictionary

这两个类分别是 CollectionDictionary 类的子类,并且可以使用可选的起始项目集构造。然而,在实例化过程中,唯一必需的参数是可接受的类或接口的 完全限定名称

<?php

namespace App;

use Fusion\Collection\CollectionFactory;

require '../vendor/autoload.php';

class Apple { /* ... */ }

$apples = CollectionFactory::newTypedCollection(Apple::class);

//Only instances of Apple are allowed
$apples->add(new Apple())
       ->add(new Apple())
       ->add(new Apple());

var_dump(count($apples)); //int (3)

// ... or ...

$setOfApples = [new Apple(), new Apple(), new Apple()];
$apples = CollectionFactory::newTypedCollection(Apple::class, $setOfApples);
var_dump(count($apples)); //int (3)

TypedDictionary 变体类似,但是需要字符串键。

<?php
    
namespace App;
    
use Fusion\Collection\CollectionFactory;

require '../vendor/autoload.php';

interface AppleInterface { /* ... */ }

class RedDelicious implements AppleInterface { /* ... */ }
class GrannySmith implements AppleInterface { /* ... */ }
class Gala implements AppleInterface { /* ... */ }

$appleBasket = CollectionFactory::newTypedDictionary(AppleInterface::class);

$appleBasket->add('redDelicious', new RedDelicious())
            ->add('grannySmith', new GrannySmith())
            ->add('gala', new Gala());

与标准 CollectionDictionary 类一样,不允许使用 null 值。

异常情况

库定义了 CollectionException 异常,在以下情况下会抛出此异常

集合

  • 添加 null 值。
  • null 替换现有值。
  • 使用不在集合中的索引调用 find()
  • 直接访问不存在的索引。
  • 访问非整数的索引。

TypedCollection

  • Collection 相同的条件适用。
  • 向集合中添加(或替换)不符合接受类型的实例。

字典

  • 添加 null 值。
  • null 替换现有值。
  • 使用不在集合中的键调用 find()
  • 直接访问不存在的键。
  • 访问非字符串的键。

TypedDictionary

  • Dictionary 相同的条件适用。
  • 向字典中添加(或替换)不符合接受类型的实例。

手动实例化

此库中的每个集合对象都可以使用它们的构造函数手动实例化,而不是使用 CollectionFactory 类。构造函数签名与工厂版本中的签名相似,但增加了一个参数,即 CollectionValidationInterface 的实例,它负责对集合操作进行完整性检查。

每个构造函数签名如下

  • Collection::__construct(CollectionValidationInterface $validator, array $items = []);
  • Dictionary::__construct(CollectionValidationInterface $validator, array $items = []);
  • TypedCollection::__construct(CollectionValidationInterface $validator, string $acceptedType, array $items = []);
  • TypedDictionary::__construct(CollectionValidationInterface $validator, string $acceptedType, array $items = []);

该库提供了CollectionValidationInterface的实现,形式为CollectionValidator类。以下是创建集合对象的替代方法

<?php

namespace App;

use Fusion\Collection\Collection;
use Fusion\Collection\CollectionValidator;

require '../vendor/autoload.php';

$validator = new CollectionValidator();
$collection = new Collection($validator, ['foo', 'bar', 'baz']);

var_dump(count($collection)); //int (3)

上述模式对剩余的集合对象同样适用。只需创建一个CollectionValidationInterface的实例,并将其作为构造函数的第一个参数传递。