eboreum/collections 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

eboreum/collections

Composer 安装命令:

composer require eboreum/collections

包简介

Wish you had generics in PHP? This library provides a sensible means of managing collections of data (i.e. arrays with restrictions), immutably, until such a time that PHP generics are bestowed upon us.

README 文档

README

license pipeline status coverage report PHPStan Level

eboreum-collections-logo

Wish you had generics in PHP? This library provides a sensible means of managing collections of data (i.e. arrays with restrictions), immutably, until such a time that PHP generics are bestowed upon us.

[comment]: # (The README.md is generated using dev/make-readme.php)

Comes fully equipped with phpstan generics annotations. For details, see: https://phpstan.org/blog/generics-in-php-using-phpdocs

The main goals of this library are:

  1. Accuracy.
    • You know with certainty what the collections in your code base can and must contain.
  2. Safety.
    • Immutability prevents unintentional modifications of collections.
    • You get an exception as soon as an invalid element is encountered.

It is not intended for speed. If you need speed in certain areas, you still have e.g. raw array manipulation you can rely on.

Requirements

"php": "^8.5",
"eboreum/caster": "^3.0",
"eboreum/exceptional": "^3.0"

For more information, see the composer.json file.

Installation

Via Composer (https://packagist.org/packages/eboreum/collections):

composer install eboreum/collections

Via GitLab:

git clone git@gitlab.com:eboreum/collections.git

Fundamentals

This library has two core components:

  1. The class Eboreum\Collections\Collection.
  2. The interface Eboreum\Collections\Contract\CollectionInterface.

Eboreum\Collections\Collection by itself imposes no restrictions and may used for storing any data type. It can be thought of as a fancy array. However, it has two crucial differences and advantages over simple arrays: It's immutable and it's type hinted, including annotations for generics (https://phpstan.org/blog/generics-in-php-using-phpdocs).

The true power of this library shows once you start making collection classes, extending Eboreum\Collections\Collection, which have restrictions.

This library comes equipped with the following simple data type collection classes:

  • Eboreum\Collections\FloatCollection: A collection, which only ever contains float numbers.
  • Eboreum\Collections\IntegerCollection: A collection, which only ever contains integers.
  • Eboreum\Collections\ObjectCollection: A collection, which only ever contains objects – any objects. More on how to make collections for specific class instances below.
  • Eboreum\Collections\StringCollection: A collection, which only ever contains strings.

The real shine comes when we start making restrictions on the contents of the collection classes, for instance restrictions on specific classes.

This library has the following predefined class collections, all located under the namespace \Eboreum\Collections\Object_:

  • ClosureCollection: A collection, which may and will only ever contain instances of \Closure.
  • DateTimeCollection: A collection, which may and will only ever contain instances of \DateTime.
  • DateTimeImmutableCollection: A collection, which may and will only ever contain instances of \DateTimeImmutable.
  • DateTimeInterfaceCollection: A collection, which may and will only ever contain instances of \DateTimeInterface.
  • DirectoryCollection: A collection, which may and will only ever contain instances of \Directory.
  • ErrorCollection: A collection, which may and will only ever contain instances of \Error.
  • ExceptionCollection: A collection, which may and will only ever contain instances of \Exception.
  • SplFileInfoCollection: A collection, which may and will only ever contain instances of \SplFileInfo.
  • SplFileObjectCollection: A collection, which may and will only ever contain instances of \SplFileObject.
  • ThrowableCollection: A collection, which may and will only ever contain instances of \Throwable.
  • stdClassCollection: A collection, which may and will only ever contain instances of \stdClass.

You may use the above files as inspiration on how to build your own specific class collections.

The above classes utilize the abstract class \Eboreum\Collections\Abstraction\AbstractNamedClassOrInterfaceCollection and subsequently the interface \Eboreum\Collections\Contract\ObjectCollectionInterface.

Make collections for anything – not just classes

You may make restrictions for anything – not just classes – including unions (https://php.watch/versions/8.0/union-types). Essentially, you merely have to override the isElementAccepted method in the collection class you are implementing.

Need something that will accept both integers and float numbers (a union)?

Simply do the following:

/**
 * {@inheritDoc}
 */
public static function isElementAccepted($element): bool
{
    return is_int($element) || is_float($element);
}

Do remember: If you utilize phpstan, you should also add and/or update the @template and its references throughout your custom collection class.

You should also override methods such as current, find, first, etc. with a suitable return type. For instance:

PHP ^8.1:

/**
 * {@inheritDoc}
 */
public function current(): int|float
{
    // ...
}

Notice: Intersection types (https://php.watch/versions/8.1/intersection-types) are not supported as they are not supported by PHP 8 due to https://wiki.php.net/rfc/nullable_intersection_types having been declined.

The reason is that methods such as current, find, first, etc. cannot have nullable return types when handling intersections.

Why is immutability necessary?

Simply put: You unintentionally risk changing mutable ("non-immutable") objects when they are being passed around the code base. You and your team may know not to change a mutable object in code bases you control, but third-party libraries (e.g. via Composer) certainly will not respect your rules. Eventually, someone in your team will forget about your "do-not-change" rule and introduce an ugly bug, which often times is hard to track down.

Real-world example of a mutable object incident

Imagine you have a database ORM (Doctrine, Eloquent, etc.). If you use DateTime instead of DateTimeImmutable, passing that instance of DateTime around may change it. Consider this: The instance of DateTime was used to set an end date from which point a user can no longer log in to your application. The same instance of DateTime was used across 100 users (e.g. for optimization reasons). Now your code, because of the change on the DateTime instance, inadvertently blocked 100 users from using your application. Such a type of bug is very hard to find the root cause for.

Tests

Test/development requirements

"overtrue/phplint": "^9.7",
"phpstan/phpstan": "^2.1.54",
"phpunit/phpunit": "^12.1",
"slevomat/coding-standard": "^8.28",
"squizlabs/php_codesniffer": "^4.0",
"symfony/polyfill-intl-icu": "^1.31"

Running tests

For all unit tests, first follow these steps:

cd tests
php ../vendor/bin/phpunit

License & Disclaimer

See LICENSE file. Basically: Use this library at your own risk.

Contributing

We prefer that you create an issue and or a merge request at https://gitlab.com/eboreum/collections, and have a discussion about a feature or bug here.

Branch rules

main = 3.x (not a tag): PHP ^8.5.

Previous branches:

  • 1.x: PHP ^8.1.
  • 2.x: PHP ^8.3.

No \ArrayAccess!

This library does not and will not utilize \ArrayAccess (https://www.php.net/manual/en/class.arrayaccess.php).

It goes against the immutable nature of this library, it's a little bit evil, and it makes code unnecessarily obscure.

Credits

Authors

Acknowledgements

doctrine/collections

This library is greatly inspired by https://packagist.org/packages/doctrine/collections (https://github.com/doctrine/collections) and some of the code is indeed copied from that library (acknowledged by inclusion of the LICENSE file contents at the top of select files, as required by https://github.com/doctrine/collections/blob/94918256daa6ac99c7e5774720c0e76f01936bda/LICENSE).

Laravel collection

For certain methods, we have also drawn inspiration from https://laravel.com/docs/12.x/collections.

eboreum/collections 适用场景与选型建议

eboreum/collections 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 7.37k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2022 年 04 月 22 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 eboreum/collections 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 eboreum/collections 我们能提供哪些服务?
定制开发 / 二次开发

基于 eboreum/collections 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 7.37k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 2
  • 点击次数: 1
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2022-04-22