yomy / datastructures
数据结构
Requires
- php: >=7.0
Requires (Dev)
- phpunit/phpunit: ^6
This package is auto-updated.
Last update: 2024-09-07 21:59:52 UTC
README
PHP的常见数据结构
安装和文档
- 作为 [Composer] 包 [yomy/datastructures] 提供。
这个库是关于什么的
此库添加了可以用于更好地组织对象的数据结构类
值对象的示例
创建对象
use YomY\DataStructures\ValueObject\ValueObject; $object = ValueObject::instance(1);
从对象获取值
$value = $object->getValue();
具有相同值的对象将是相同的对象
$object1 = ValueObject::instance(1); $object2 = ValueObject::instance(1); //These two are the same objects ($object1 === $object2)
您可以在方法中使用类型提示
public function doSomething(ValueObject $valueObject) { $value = $valueObject->getValue(); ... }
您可以扩展对象以进行更详细的类型提示
class UserId extends ValueObject {} class DataId extends ValueObject {} ... public function doSomething(UserId $userId, DataId $dataId) { ... }
不同类或变量类型的对象是不同的
$object1 = ValueObject::instance(''); $object2 = ValueObject::instance(null); $object3 = ValueObject::instance(false); $object4 = ExtendedValueObject::instance(''); $object5 = ExtendedValueObject::instance(null); $object6 = ExtendedValueObject::instance(false); //All of the above are different
除了强(===)比较运算符外,您还可以使用 equals() 方法
$object1 = ValueObject::instance(1); $object2 = ValueObject::instance(1); $same = $object1->equals($object2); //true
通常,值对象的反序列化是被禁止的,因为这会破坏通过引用比较对象的能力。但是,您可能有一些不关心严格比较的情况,需要反序列化对象。您可以在自定义对象中添加 WeakValueObjectTrait 使用,这将允许反序列化它,并在使用 equals() 方法时通过值而不是引用比较对象
class MyWeakObject extends ValueObject { use WeakValueObjectTrait; } ... $weakObject1 = MyWeakObject::instance(1); $serializedWeakObject = serialize($weakObject1); $weakObject2 = unserialize($serializedWeakObject); //These two objects are "equal" but not the same $weakObject1->equals($weakObject2); //true //On regular value objects this would be false
枚举值对象的示例
创建枚举对象
use YomY\DataStructures\ValueObject\EnumValueObject; class Category extends EnumValueObject { const FIRST = 1; const SECOND = 2; const THIRD = 3; }
创建枚举对象
$category = Category::instance(Category::FIRST);
或通过引用键
$category = Category::FIRST();
如果您尝试实例化无效的值,将会出错
$category = Category::instance('missing_value'); $category = Category::MISSING();
正整数值对象的示例
由于值对象通常用作具有整数键的数据库实体的标识符,因此正整数值对象确保了用于此目的的有效键对象
创建对象
use YomY\DataStructures\ValueObject\PositiveIntValueObject; $object1 = PositiveIntValueObject::instance(1); $object2 = PositiveIntValueObject::instance('1'); //These two are the same objects ($object1 === $object2)
通常,数据库中的 id 键不能为 0,因此这些对象是无效的
$object = PositiveIntValueObject::instance(0); $object = PositiveIntValueObject::instance('0');
当然,与基本值对象一样,这些对象旨在在扩展类中使用。
class UserId extends PositiveIntValueObject {} class DataId extends PositiveIntValueObject {} $user = UserId::instance(42); $data = DataId::instance(42); //these two are not the same
GenericCollection 使用示例
创建集合对象
use YomY\DataStructures\Collection\GenericCollection; $collection = new GenericCollection();
将对象添加到集合中
$collection->add(1); $collection->add(2); $collection->add(3); $collection->add('string'); $collection->add(true); $collection->add(false); $collection->add(null); $collection->add($anObject); $collection->add(['an', 'array']);
您也可以使用数组语法添加对象
$collection[] = 1;
对象可以多次添加
$collection->add(1); $collection->add(1); $collection->add(1);
集合支持一次性添加值数组的操作
$values = [1, 2, 3]; $collection->addArray($values);
从集合中删除对象 - 删除对象的所有实例
$collection->remove(1);
从集合中获取对象
$objects = $collection->getAll();
注意,您 不能 使用数组语法获取对象
$object = $collection[3]; //This will throw an exception
您也可以遍历集合本身
foreach ($collection as $object) { ... }
计算集合中对象的数量
$count = $collection->count();
验证集合是否为空
$empty = $collection->isEmpty();
验证集合是否包含对象
$contains = $collection->contains(1);
您可以浅拷贝集合
$copy = $collection->copy();
您可以将另一个集合附加到集合中
$collection->append($collection2); //$collection now has gets items from $collection2 along it's own items
集合支持自定义排序其对象
$values = [9, 8, 7, 6, 5, 4, 3, 2, 1]; $collection = new GenericCollection(); $collection->addArray($values); $collection->sort(function($object1, $object2) { return $object1 > $object2; }); //Collection will now have an array like //[1, 2, 3, 4, 5, 6, 7, 8, 9];
集合可以通过过滤来获取包含过滤对象的新的集合
$values = [1, 2, 3, 4, 5, 6, 7, 8, 9]; $collection = new GenericCollection(); $collection->addArray($values); $filtered = $collection->filter(function($object) { return $object > 5; }); //$filtered contains [6, 7, 8, 9] //original collection is not affected
集合可以通过回调方法转换为数组。这允许从对象中提取底层数据或进行自定义计算
$values = [1, 2, 3, 4, 5, 6, 7, 8, 9]; $collection = new GenericCollection(); $collection->addArray($values); $transformed = $collection->transformToArray(function($object) { //Here we decide what to return in place of each item return new CustomWrapper($object); });
集合可以转换(附加)到另一个集合中
$values = [1, 2, 3, 4, 5, 6, 7, 8, 9]; $collection = new GenericCollection(); $collection->addArray($values); $destinationCollection = new GenericCollection(); $destinationCollection->addArray($values); $collection->transformToCollection($destinationCollection); //$destinationCollection now has appended items from $collection
ObjectCollection 使用示例
ObjectCollection 是 GenericCollection 的扩展,旨在仅包含特定类的对象。
创建特定类型的 ObjectCollection
$objectCollection = new ObjectCollection(ExampleObject1::class);
GenericCollection 的所有方法几乎以相同的方式工作,只是不允许添加在 Collection 构造函数中传递的确切类型的对象。
$objectCollection = new ObjectCollection(ExampleObject1::class); $objectCollection->add(new ExampleObject1());
尝试添加错误类型的对象将抛出 InvalidArgumentException
$objectCollection = new ObjectCollection(ExampleObject1::class); $objectCollection->add(new DifferentObject()); //This will throw an InvalidArgumentException
集合也可以与扩展对象一起工作
class ExtendedExampleObject1 extends ExampleObject1 {} $objectCollection = new ObjectCollection(ExampleObject1::class); $objectCollection->add(new ExampleObject1()); $objectCollection->add(new ExtendedExampleObject1());
ObjectCollection 的主要目的是拥有一个自定义命名的集合
class User {...} class UserCollection extends ObjectCollection { public function __construct() { parent::__construct(User::class); } }
拥有此类集合允许在代码中进行类型提示,并且我们确信该集合只包含特定类型的对象。
function someMethod(UserCollection $userCollection) { foreach ($userCollection as $user) { //Here we can use individual users from collection } } ... $userCollection = new UserCollection(); $userCollection->add($user1); $userCollection->add($user2); $userCollection->add($user3); someMethod($userCollection);
在某些情况下,我们需要尝试从一个未知对象数组中填充一个集合。tryAddArray() 方法将允许安全地尝试添加所有正确类型的对象,并提供一个无法添加的对象数组。
$failed = $objectCollection->tryAddArray($objects); //the $failed array will contain objects that were not added to collection
KeyValueCollection 使用示例
KeyValueCollection 是一个旨在包含键=>值对的集合。内部,此集合持有 Pair 类型的对象,但目的是不直接使用这些 Pair 对象,而是通过在集合对象上直接设置键和值。
$keyValueCollection = new KeyValueCollection();
应通过 put() 和 get() 方法使用 KeyValueCollection。
$keyValueCollection->put('key', 'value'); $value = $keyValueCollection->get('key'); //$value will contain the string 'value'
使用 KeyValueCollection 时,您也可以使用数组语法。
$keyValueCollection['key'] = 'value'; $value = $keyValueCollection['key']; //$value will contain the string 'value'
KeyValueCollection 具有唯一的键。这意味着将某物放在已存在的键上将会覆盖集合中的值。
$keyValueCollection->put('key', 'value'); $keyValueCollection->put('key', 'newValue'); $value = $keyValueCollection->get('key'); //$value will contain the string 'newValue'
现在,您可能认为这仅仅是模拟关联数组,那么为什么还要使用它呢?
KeyValueCollection 的强大之处在于它可以持有对象作为键,因此您可以有
class UserId {...} //A Value Object class class User {...} //A user details object class class UserCollection extends KeyValueCollection { public function __construct() { parent::__construct(UserId::class, User::class); } } ... //Just for example. These would probably have been built and used inside your application $userId = new UserId(); $user = new User(); ... $userCollection = new UserCollection(); $userCollection->put($userId, $user); $user = $userCollection->get($userId);