createQueryBuilder() ->andWhere(Operator::andX($this->specs)); if ($useTotalCount) { $qb->addCalcRows(); } $result = $qb->execute(); if ($useTotalCount) { $totalCount = (int) sqlFetchAssoc(sqlQuery('SELECT FOUND_ROWS() as total_count'))['total_count']; } $items = []; foreach ($result as $item) { $items[$item['id']] = $this->createItem($item); } $collection = new static::$collectionClass($items); foreach ($this->resultModifiers as $callback) { $callback($collection); } return $collection; } public function orderBy(string $sort, ?string $order = null): self { $this->andSpec(function (QueryBuilder $qb) use ($sort, $order) { $qb->orderBy($sort, $order); }); return $this; } public function limit(int $count, ?int $offset = null): self { $this->andSpec(function (QueryBuilder $qb) use ($count, $offset) { if (isset($offset)) { $qb->setFirstResult($offset); } $qb->setMaxResults($count); }); return $this; } public function addResultModifiers(callable $resultModifier): self { $this->resultModifiers[] = $resultModifier; return $this; } public function andSpec(?callable $spec): self { if ($spec) { $this->specs[] = $spec; } return $this; } abstract protected function createItem(array $item): mixed; abstract protected function createQueryBuilder(): QueryBuilder; }