diff --git a/src/Model.php b/src/Model.php index f95427c..a9c3241 100644 --- a/src/Model.php +++ b/src/Model.php @@ -9,6 +9,8 @@ /** * Models represent single database tables or parts of it. * They are also used to interact with the tables, i.e. in order to query for data. + * + * @template TModel of Model */ abstract class Model implements \ArrayAccess, \IteratorAggregate { @@ -76,7 +78,7 @@ public function getColumnDefinitions() * * @param Connection $db * - * @return Query + * @return Query */ public static function on(Connection $db) { diff --git a/src/Query.php b/src/Query.php index 14896d4..c9f7941 100644 --- a/src/Query.php +++ b/src/Query.php @@ -26,6 +26,9 @@ /** * Represents a database query which is associated to a model and a database connection. + * + * @template TRow of Model + * @implements IteratorAggregate */ class Query implements Filterable, LimitOffsetInterface, OrderByInterface, Paginatable, IteratorAggregate { @@ -53,10 +56,10 @@ class Query implements Filterable, LimitOffsetInterface, OrderByInterface, Pagin /** @var Connection Database connection */ protected $db; - /** @var string Class to return results as */ + /** @var class-string Class to return results as */ protected string $resultSetClass = ResultSet::class; - /** @var Model Model to query */ + /** @var TRow Model to query */ protected $model; /** @var array Columns to select from the model (or its relations). If empty, all columns are selected */ @@ -113,7 +116,7 @@ public function setDb(Connection $db): static /** * Get the class to return results as * - * @return string + * @return class-string */ public function getResultSetClass(): string { @@ -123,7 +126,7 @@ public function getResultSetClass(): string /** * Set the class to return results as * - * @param string $class + * @param class-string $class * * @return $this * @@ -145,7 +148,7 @@ public function setResultSetClass(string $class): static /** * Get the model to query * - * @return Model + * @return TRow */ public function getModel() { @@ -155,7 +158,7 @@ public function getModel() /** * Set the model to query * - * @param Model $model + * @param TRow $model * * @return $this */ @@ -572,7 +575,7 @@ public function createHydrator(): Hydrator * Derive a new query to load the specified relation from a concrete model * * @param string $relation - * @param Model $source + * @param TRow $source * * @return static * @@ -593,7 +596,7 @@ public function derive($relation, Model $source): static * * @param Model $target The model to query * @param string $targetPath The target's absolute relation path - * @param ?Model $from The source model + * @param ?TRow $from The source model * @param bool $link Whether the query should be linked to the parent query * * @return static @@ -658,7 +661,7 @@ public function dump(): array /** * Execute the query * - * @return ResultSet + * @return ResultSet */ public function execute(): ResultSet { @@ -671,7 +674,7 @@ public function execute(): ResultSet /** * Fetch and return the first result * - * @return Model|null Null in case there's no result + * @return ?TRow Null in case there's no result */ public function first(): ?Model { @@ -698,7 +701,7 @@ public function peekAhead(bool $peekAhead = true): static /** * Yield the query's results * - * @return Generator + * @return Generator */ public function yieldResults(): Generator { @@ -723,6 +726,11 @@ public function count(): int return $this->count; } + /** + * Get the query's result set + * + * @return Traversable + */ public function getIterator(): Traversable { return $this->execute(); diff --git a/src/ResultSet.php b/src/ResultSet.php index dc4e2c1..a1e8ab0 100644 --- a/src/ResultSet.php +++ b/src/ResultSet.php @@ -7,19 +7,31 @@ use Iterator; use Traversable; +/** + * @template TRow of Model + * @implements Iterator + */ class ResultSet implements Iterator { + /** @var ArrayIterator */ protected ArrayIterator $cache; /** @var bool Whether cache is disabled */ protected bool $isCacheDisabled = false; + /** @var Generator */ protected Generator $generator; protected ?int $limit; protected ?int $position = null; + /** + * Create a new result set from the given traversable + * + * @param Traversable $traversable + * @param ?int $limit + */ public function __construct(Traversable $traversable, ?int $limit = null) { $this->cache = new ArrayIterator(); @@ -30,7 +42,7 @@ public function __construct(Traversable $traversable, ?int $limit = null) /** * Create a new result set from the given query * - * @param Query $query + * @param Query $query * * @return static */ @@ -63,6 +75,7 @@ public function hasResult(): bool return $this->generator->valid(); } + /** @return TRow */ #[\ReturnTypeWillChange] public function current() { @@ -135,6 +148,13 @@ protected function advance(): void } } + /** + * Yield the given traversable + * + * @param Traversable $traversable + * + * @return Generator + */ protected function yieldTraversable(Traversable $traversable) { foreach ($traversable as $key => $value) {