nkopylov / php-typed-collections
为PHP实体生成静态类型集合
v0.0.1
2022-10-04 07:36 UTC
Requires
- php: ^7.4|^8.0
Requires (Dev)
- phpunit/phpunit: ^9.1
README
为PHP实体生成静态类型集合。
集合示例
<?php /** * Autogenerated. * Time: 2022-10-04 06:17:44 */ declare(strict_types=1); namespace Nkopylov\Test\PhpCollections; use JetBrains\PhpStorm\Pure; use Nkopylov\Test\PhpCollections\TestClass as CollectionEntity; /** * Autogenerated typed collection for Nkopylov\Test\PhpCollections\TestClass objects. * Check nkopylov/php-typed-collections for more information * * @implements \Iterator<mixed, CollectionEntity> * @implements \ArrayAccess<mixed, CollectionEntity> * @codeCoverageIgnore */ class TestCollection_testCollection implements \Iterator, \ArrayAccess { /** * @var CollectionEntity[] */ private array $elements = []; /** * @var callable */ private $idMapper; /** * @phpstan-pure * Creates new collection * @return static */ public static function create(): self { return new static(function() {static $counter = 0; return $counter++;}); } final public function __construct(callable $idMapper) { $this->idMapper = $idMapper; } /** * @phpstan-pure * Returns the first entity from the collection. * @return CollectionEntity|null */ public function first(): ?CollectionEntity { if ($this->count() === 0) { return null; } $this->rewind(); return $this->current(); } /** * {@inheritdoc} * @return CollectionEntity */ public function current(): CollectionEntity { $entity = current($this->elements); if ($entity === false) { throw new \LogicException('Collection is empty'); } return $entity; } /** * {@inheritdoc} */ public function next(): void { next($this->elements); } /** * {@inheritdoc} */ public function key(): mixed { return key($this->elements); } /** * {@inheritdoc} */ public function valid(): bool { return $this->key() !== null; } /** * {@inheritdoc} */ public function rewind(): void { reset($this->elements); } /** * {@inheritdoc} */ public function offsetExists($offset): bool { return isset($this->elements[$offset]); } /** * {@inheritdoc} */ public function offsetSet($offset, $value): void { if (!($value instanceof CollectionEntity)) { throw new \InvalidArgumentException(sprintf("Can't insert object of class %s to %s", get_class($value), self::class)); } $this->elements[$offset] = $value; } /** * {@inheritdoc} */ public function offsetUnset($offset): void { unset($this->elements[$offset]); } /** * {@inheritdoc} */ public function offsetGet($offset): CollectionEntity { return $this->elements[$offset]; } /** * Add entity to the collection * @param CollectionEntity $item * @return $this */ public function add(CollectionEntity $item): self { $this->elements[($this->idMapper)($item)] = $item; return $this; } /** * Add entities from array to the collection * @param iterable<CollectionEntity> $items * @return $this */ public function addArray(iterable $items): self { foreach ($items as $item) { $this->add($item); } return $this; } /** * Remove entity from collection by id * @param mixed $id * @return $this */ public function remove($id): self { unset($this->elements[$id]); return $this; } /** * Check if entity exists by id * @param mixed $id * @return bool */ public function has($id): bool { return isset($this->elements[$id]); } /** * Get entity by id. * @param mixed $id * @return CollectionEntity|null */ public function get($id): ?CollectionEntity { return $this->elements[$id] ?? null; } /** * @phpstan-pure * Map collection by given callable. Creates new collection * @param callable $mapper * @return static */ public function map(callable $mapper): self { return (new static($this->idMapper)) ->addArray(array_map($mapper, $this->elements)); } /** * @phpstan-pure * Creates a new collection mapped by key defined by given callable * @param callable $idMapper * @return static */ public function mapKeys(callable $idMapper): self { return (new static($idMapper))->addArray($this->elements); } /** * Map collection to array by given callable. * @param callable $mapper * @return array<mixed, CollectionEntity> */ public function mapToArray(callable $mapper): array { return array_map($mapper, $this->elements); } /** * Transform current collection with given function * @param callable $mapper * @return $this */ public function transform(callable $mapper): self { $this->elements = array_map($mapper, $this->elements); return $this; } /** * @phpstan-pure * Filter collection by given callback. Returns new collection * @param callable $mapper * @return static */ public function filter(callable $mapper): self { return (new static($this->idMapper))->addArray(array_filter($this->elements, $mapper) ?? []); } /** * Sort collection by given callback * @param callable $sorter * @return $this */ public function sort(callable $sorter): self { uasort($this->elements, $sorter); return $this; } /** * @phpstan-pure * Split collection on the given number of chunks. Returns array of new collections * @param int $size * @return array<int, self> */ public function chunk(int $size): array { return array_map( fn(array $chunk) => (new static($this->idMapper))->addArray($chunk), array_chunk($this->elements, $size) ); } /** * @phpstan-pure * Groups collection by some value returned by a given callable * @param callable $keyResolver * @return static[] */ public function groupBy(callable $keyResolver): array { $result = []; foreach ($this->elements as $element) { $key = $keyResolver($element); if (!isset($result[$key])) { $result[$key] = new static($this->idMapper); } $result[$key]->add($element); } return $result; } /** * Returns collection size. * @return int */ public function count(): int { return count($this->elements); } /** * Clear collection * @return $this */ public function clear(): self { $this->elements = []; return $this; } /** * @phpstan-pure * Merges current collection with a given collection. Returns new collection * @param self $collection * @return self */ public function merge(self $collection): self { return (clone $collection)->addArray($this->elements); } /** * @phpstan-pure * Slices collection. Returns new collection as a result * @param int $offset * @param int|null $limit * @return static */ public function slice(int $offset, ?int $limit = null): self { if ($offset === 0 && empty($limit)) { return $this; } $collection = new static($this->idMapper); $collection->addArray(array_slice($this->elements, $offset, $limit, true)); return $collection; } /** * Cast collection to array * @return CollectionEntity[] */ public function toArray(): array { return $this->elements; } /** * Return collection keys * @return array<mixed> */ public function keys(): array { return array_keys($this->elements); } }
安装
使用Composer将此包作为依赖项安装。
composer require nkopylov/php-typed-collections
用法
vendor/bin/typed-collections generate <--class=> <--generated-class-name=> <--path=> <--namespace=> <--template=> <--parent-class=> <--interfaces=> <--traits=>
generate命令生成一个新的静态类型集合,并将其放在可收集的PHP类旁边。
命令参数
--class- 必须参数。包含可收集实体的完整类名。--generated-class-name- 默认集合类名为Collection。如果您想重新定义此名称,请使用此参数指定类的短名称。--namespace- 默认情况下,集合将创建在可收集类的相同命名空间中。如果您想重新定义命名空间,请使用此参数指定完整的命名空间名称。--path- 默认情况下,集合将放置在可收集类旁边的文件系统中。如果您更改了命名空间或需要将此集合放置在其他位置,请使用此参数指定新路径。--template- 默认模板已设置。它包含默认方法,并支持\Iterable和\ArrayAccess接口。如果您想设置自己的模板,请使用此参数。有关示例,请参阅src/templates/collection.template。--parent-class- 如果您想使生成的集合扩展某个类,请使用此参数。--interfaces- 如果您需要生成的集合实现某些接口,请使用此参数。为每个接口提供完整名称,用逗号分隔接口。--traits- 如果您需要生成的集合使用某些特性,请使用此参数。提供完整特性名称列表,用逗号分隔。
示例
vendor/bin/typed-collections generate --class=\MyEntity
此命令将生成一个名为\MyEntityCollection的集合,并将其放置在\MyEntity类旁边。
键映射
php-typed-collections支持三种为集合实体设置键的方法
- 通过int自动递增自动生成键(默认)
- 在可收集类中的
getId()方法。实现\Nkopylov\PhpCollections\ObjectWithIdentifier,使生成器知道您的类支持此功能。 - 您还可以提供自己的函数,该函数将用于键生成。有关更多信息,请参阅
\Nkopylov\PhpCollections\Mappable接口。此外,测试对象\Nkopylov\Test\PhpCollections\TestObjectWithMappable将有助于您。
贡献
欢迎贡献!在向此项目贡献之前,请熟悉CONTRIBUTING.md。
要开发此项目,您需要PHP 7.4或更高版本和Composer。
在本地克隆此存储库后,执行以下命令
cd /path/to/repository
composer install --dev
现在,您可以开始开发了!