Files
FendxPHP/app/Dto/CollectionDto.php

441 lines
8.5 KiB
PHP
Raw Permalink Normal View History

<?php
declare(strict_types=1);
namespace App\Dto;
/**
* 数据集合传输对象
*/
class CollectionDto extends BaseDto
{
private array $items = [];
private int $count = 0;
private array $meta = [];
public function __construct(array $items = [])
{
$this->items = $items;
$this->count = count($items);
}
public function getItems(): array
{
return $this->items;
}
public function setItems(array $items): self
{
$this->items = $items;
$this->count = count($items);
return $this;
}
public function getCount(): int
{
return $this->count;
}
public function getMeta(): array
{
return $this->meta;
}
public function setMeta(array $meta): self
{
$this->meta = $meta;
return $this;
}
/**
* 添加项目
*/
public function add(mixed $item): self
{
$this->items[] = $item;
$this->count++;
return $this;
}
/**
* 添加元数据
*/
public function addMeta(string $key, mixed $value): self
{
$this->meta[$key] = $value;
return $this;
}
/**
* 检查是否为空
*/
public function isEmpty(): bool
{
return $this->count === 0;
}
/**
* 检查是否不为空
*/
public function isNotEmpty(): bool
{
return $this->count > 0;
}
/**
* 获取第一个项目
*/
public function first(): mixed
{
return $this->items[0] ?? null;
}
/**
* 获取最后一个项目
*/
public function last(): mixed
{
return $this->items[$this->count - 1] ?? null;
}
/**
* 获取指定索引的项目
*/
public function get(int $index): mixed
{
return $this->items[$index] ?? null;
}
/**
* 映射集合
*/
public function map(callable $callback): self
{
$new = clone $this;
$new->items = array_map($callback, $this->items);
return $new;
}
/**
* 过滤集合
*/
public function filter(callable $callback): self
{
$new = clone $this;
$new->items = array_filter($this->items, $callback);
$new->count = count($new->items);
return $new;
}
/**
* 排序集合
*/
public function sort(callable $callback): self
{
$new = clone $this;
$items = $this->items;
usort($items, $callback);
$new->items = $items;
return $new;
}
/**
* 反转集合
*/
public function reverse(): self
{
$new = clone $this;
$new->items = array_reverse($this->items);
return $new;
}
/**
* 获取唯一的集合
*/
public function unique(): self
{
$new = clone $this;
$new->items = array_unique($this->items);
$new->count = count($new->items);
return $new;
}
/**
* 切片集合
*/
public function slice(int $offset, ?int $length = null): self
{
$new = clone $this;
$new->items = array_slice($this->items, $offset, $length);
$new->count = count($new->items);
return $new;
}
/**
* 限制集合大小
*/
public function take(int $limit): self
{
return $this->slice(0, $limit);
}
/**
* 跳过指定数量
*/
public function skip(int $count): self
{
return $this->slice($count);
}
/**
* 分块集合
*/
public function chunk(int $size): array
{
return array_chunk($this->items, $size);
}
/**
* 求和
*/
public function sum(callable|string $key = null): float
{
if ($key === null) {
return array_sum($this->items);
}
if (is_callable($key)) {
return array_sum(array_map($key, $this->items));
}
return array_sum(array_column($this->items, $key));
}
/**
* 求平均值
*/
public function avg(callable|string $key = null): float
{
if ($this->isEmpty()) {
return 0;
}
return $this->sum($key) / $this->count;
}
/**
* 求最大值
*/
public function max(callable|string $key = null): mixed
{
if ($this->isEmpty()) {
return null;
}
if ($key === null) {
return max($this->items);
}
if (is_callable($key)) {
$values = array_map($key, $this->items);
return max($values);
}
return max(array_column($this->items, $key));
}
/**
* 求最小值
*/
public function min(callable|string $key = null): mixed
{
if ($this->isEmpty()) {
return null;
}
if ($key === null) {
return min($this->items);
}
if (is_callable($key)) {
$values = array_map($key, $this->items);
return min($values);
}
return min(array_column($this->items, $key));
}
/**
* 查找项目
*/
public function find(callable $callback): mixed
{
foreach ($this->items as $item) {
if ($callback($item)) {
return $item;
}
}
return null;
}
/**
* 检查是否存在项目
*/
public function contains(mixed $item): bool
{
return in_array($item, $this->items, true);
}
/**
* 检查是否包含满足条件的项目
*/
public function containsWhere(callable $callback): bool
{
return $this->find($callback) !== null;
}
/**
* 获取所有键
*/
public function keys(): array
{
return array_keys($this->items);
}
/**
* 获取所有值
*/
public function values(): array
{
return array_values($this->items);
}
/**
* 合并其他集合
*/
public function merge(self $other): self
{
$new = clone $this;
$new->items = array_merge($this->items, $other->getItems());
$new->count = count($new->items);
return $new;
}
/**
* 转换为分页对象
*/
public function toPagination(int $page = 1, int $pageSize = 10): PaginationDto
{
$offset = ($page - 1) * $pageSize;
$items = array_slice($this->items, $offset, $pageSize);
return PaginationDto::create($items, $this->count, $page, $pageSize);
}
/**
* 创建空集合
*/
public static function empty(): self
{
return new self([]);
}
/**
* 从数组创建集合
*/
public static function fromArray(array $items): self
{
return new self($items);
}
/**
* 创建包含单个项目的集合
*/
public static function of(mixed $item): self
{
return new self([$item]);
}
/**
* 创建范围集合
*/
public static function range(int $start, int $end): self
{
return new self(range($start, $end));
}
/**
* 转换为数组
*/
public function toArray(): array
{
return [
'items' => $this->items,
'count' => $this->count,
'meta' => empty($this->meta) ? null : $this->meta,
];
}
/**
* 转换为JSON
*/
public function toJson(): string
{
return json_encode($this->toArray(), JSON_UNESCAPED_UNICODE);
}
/**
* 实现ArrayAccess接口
*/
public function offsetExists(mixed $offset): bool
{
return isset($this->items[$offset]);
}
public function offsetGet(mixed $offset): mixed
{
return $this->items[$offset] ?? null;
}
public function offsetSet(mixed $offset, mixed $value): void
{
if ($offset === null) {
$this->items[] = $value;
} else {
$this->items[$offset] = $value;
}
$this->count = count($this->items);
}
public function offsetUnset(mixed $offset): void
{
unset($this->items[$offset]);
$this->count = count($this->items);
}
/**
* 实现Countable接口
*/
public function count(): int
{
return $this->count;
}
/**
* 实现IteratorAggregate接口
*/
public function getIterator(): \ArrayIterator
{
return new \ArrayIterator($this->items);
}
/**
* 实现JsonSerializable接口
*/
public function jsonSerialize(): array
{
return $this->toArray();
}
}