items; } public function setItems(array $items): self { $this->items = $items; $this->calculateDerivedValues(); return $this; } public function getTotal(): int { return $this->total; } public function setTotal(int $total): self { $this->total = $total; $this->calculateDerivedValues(); return $this; } public function getPage(): int { return $this->page; } public function setPage(int $page): self { $this->page = max(1, $page); $this->calculateDerivedValues(); return $this; } public function getPageSize(): int { return $this->pageSize; } public function setPageSize(int $pageSize): self { $this->pageSize = max(1, $pageSize); $this->calculateDerivedValues(); return $this; } public function getTotalPages(): ?int { return $this->totalPages; } public function getHasMore(): ?bool { return $this->hasMore; } public function getHasPrev(): ?bool { return $this->hasPrev; } public function getHasNext(): ?bool { return $this->hasNext; } public function getFrom(): ?int { return $this->from; } public function getTo(): ?int { return $this->to; } public function getFilters(): array { return $this->filters; } public function setFilters(array $filters): self { $this->filters = $filters; return $this; } public function getSorts(): array { return $this->sorts; } public function setSorts(array $sorts): self { $this->sorts = $sorts; return $this; } /** * 添加过滤器 */ public function addFilter(string $key, mixed $value): self { $this->filters[$key] = $value; return $this; } /** * 添加排序 */ public function addSort(string $field, string $direction = 'asc'): self { $this->sorts[$field] = strtolower($direction); return $this; } /** * 计算派生值 */ private function calculateDerivedValues(): void { $this->totalPages = $this->pageSize > 0 ? (int) ceil($this->total / $this->pageSize) : 0; $this->hasMore = $this->page * $this->pageSize < $this->total; $this->hasPrev = $this->page > 1; $this->hasNext = $this->page < $this->totalPages; $this->from = $this->total > 0 ? (($this->page - 1) * $this->pageSize) + 1 : null; $this->to = min($this->page * $this->pageSize, $this->total); } /** * 获取偏移量 */ public function getOffset(): int { return ($this->page - 1) * $this->pageSize; } /** * 获取限制数量 */ public function getLimit(): int { return $this->pageSize; } /** * 检查是否为第一页 */ public function isFirstPage(): bool { return $this->page === 1; } /** * 检查是否为最后一页 */ public function isLastPage(): bool { return !$this->hasNext; } /** * 获取上一页页码 */ public function getPrevPage(): ?int { return $this->hasPrev ? $this->page - 1 : null; } /** * 获取下一页页码 */ public function getNextPage(): ?int { return $this->hasNext ? $this->page + 1 : null; } /** * 创建分页对象 */ public static function create(array $items, int $total, int $page = 1, int $pageSize = 10): self { return (new self()) ->setItems($items) ->setTotal($total) ->setPage($page) ->setPageSize($pageSize); } /** * 从查询结果创建分页对象 */ public static function fromQuery(array $items, int $total, array $params = []): self { $page = (int) ($params['page'] ?? 1); $pageSize = (int) ($params['page_size'] ?? $params['limit'] ?? 10); $filters = $params['filters'] ?? []; $sorts = $params['sorts'] ?? []; return (new self()) ->setItems($items) ->setTotal($total) ->setPage($page) ->setPageSize($pageSize) ->setFilters($filters) ->setSorts($sorts); } /** * 转换为数组 */ public function toArray(): array { return [ 'items' => $this->items, 'pagination' => [ 'total' => $this->total, 'page' => $this->page, 'page_size' => $this->pageSize, 'total_pages' => $this->totalPages, 'has_more' => $this->hasMore, 'has_prev' => $this->hasPrev, 'has_next' => $this->hasNext, 'from' => $this->from, 'to' => $this->to, 'prev_page' => $this->getPrevPage(), 'next_page' => $this->getNextPage(), ], 'filters' => empty($this->filters) ? null : $this->filters, 'sorts' => empty($this->sorts) ? null : $this->sorts, ]; } /** * 获取分页信息数组 */ public function getPaginationInfo(): array { return [ 'total' => $this->total, 'page' => $this->page, 'page_size' => $this->pageSize, 'total_pages' => $this->totalPages, 'has_more' => $this->hasMore, 'has_prev' => $this->hasPrev, 'has_next' => $this->hasNext, 'from' => $this->from, 'to' => $this->to, 'prev_page' => $this->getPrevPage(), 'next_page' => $this->getNextPage(), ]; } /** * 获取SQL LIMIT子句 */ public function getSqlLimit(): string { return "LIMIT {$this->pageSize} OFFSET " . $this->getOffset(); } /** * 验证分页参数 */ public function validate(): array { $errors = parent::validate(); if ($this->page < 1) { $errors['page'] = 'Page must be greater than 0'; } if ($this->pageSize < 1 || $this->pageSize > 1000) { $errors['page_size'] = 'Page size must be between 1 and 1000'; } if ($this->total < 0) { $errors['total'] = 'Total must be greater than or equal to 0'; } return $errors; } /** * 克隆分页对象,修改页码 */ public function withPage(int $page): self { $new = clone $this; $new->setPage($page); return $new; } /** * 克隆分页对象,修改页大小 */ public function withPageSize(int $pageSize): self { $new = clone $this; $new->setPageSize($pageSize); return $new; } /** * 克隆分页对象,修改过滤器 */ public function withFilters(array $filters): self { $new = clone $this; $new->setFilters($filters); return $new; } /** * 克隆分页对象,修改排序 */ public function withSorts(array $sorts): self { $new = clone $this; $new->setSorts($sorts); return $new; } }