- Add sub-doc handling for SQLite fields - Add casting for PostgreSQL BT on numeric value - Add hasItems() to DocumentList - Fix SQL syntax problems exposed by tests
84 lines
2.4 KiB
PHP
84 lines
2.4 KiB
PHP
<?php declare(strict_types=1);
|
|
|
|
namespace BitBadger\PDODocument;
|
|
|
|
use BitBadger\PDODocument\Mapper\Mapper;
|
|
use Generator;
|
|
use PDO;
|
|
use PDOStatement;
|
|
|
|
/**
|
|
* A lazy iterator of results in a list; implementations will create new connections to the database and close/dispose
|
|
* them as required once the results have been exhausted.
|
|
*
|
|
* @template TDoc The domain class for items returned by this list
|
|
*/
|
|
class DocumentList
|
|
{
|
|
/** @var TDoc|null $_first The first item from the results */
|
|
private mixed $_first = null;
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param PDOStatement|null $result The result of the query
|
|
* @param Mapper<TDoc> $mapper The mapper to deserialize JSON
|
|
*/
|
|
private function __construct(private ?PDOStatement &$result, private readonly Mapper $mapper)
|
|
{
|
|
if ($row = $this->result->fetch(PDO::FETCH_ASSOC)) {
|
|
$this->_first = $this->mapper->map($row);
|
|
} else {
|
|
$this->result = null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Construct a new document list
|
|
*
|
|
* @param string $query The query to run to retrieve results
|
|
* @param array $parameters An associative array of parameters for the query
|
|
* @param Mapper<TDoc> $mapper A mapper to deserialize JSON documents
|
|
* @return static The document list instance
|
|
* @throws DocumentException If any is encountered
|
|
*/
|
|
public static function create(string $query, array $parameters, Mapper $mapper): static
|
|
{
|
|
$stmt = &Custom::runQuery($query, $parameters);
|
|
return new static($stmt, $mapper);
|
|
}
|
|
|
|
/**
|
|
* The items from the query result
|
|
*
|
|
* @return Generator<TDoc> The items from the document list
|
|
*/
|
|
public function items(): Generator
|
|
{
|
|
if (!$this->result) return;
|
|
yield $this->_first;
|
|
while ($row = $this->result->fetch(PDO::FETCH_ASSOC)) {
|
|
yield $this->mapper->map($row);
|
|
}
|
|
$this->result = null;
|
|
}
|
|
|
|
/**
|
|
* Does this list have items remaining?
|
|
*
|
|
* @return bool True if there are items still to be retrieved from the list, false if not
|
|
*/
|
|
public function hasItems(): bool
|
|
{
|
|
return !is_null($this->result);
|
|
}
|
|
|
|
/**
|
|
* Ensure the statement is destroyed if the generator is not exhausted
|
|
*/
|
|
public function __destruct()
|
|
{
|
|
if (!is_null($this->result)) $this->result = null;
|
|
}
|
|
}
|