From 36fd056237d319340185f701a19075909215a732 Mon Sep 17 00:00:00 2001 From: ignace nyamagana butera Date: Fri, 17 Jan 2025 17:50:19 +0100 Subject: [PATCH] Imrpove ResultSet::createFromRecords --- CHANGELOG.md | 2 ++ composer.json | 5 +++-- src/Reader.php | 30 ++++++++++++++-------------- src/ResultSet.php | 50 +++++++++++++++++++++++++++++++---------------- 4 files changed, 53 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78683cd3..27290fc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,12 +13,14 @@ All Notable changes to `Csv` will be documented in this file ### Deprecated - `Writer::relaxEnclosure` use `Writer::necessaryEnclosure` +- `ResultSet::createFromTabularDataReader` use `ResultSet::createFromRecords` ### Fixed - `Comparison::CONTAINS` must check the value is a string before calling `str_compare` [#548](https://github.com/thephpleague/csv/pull/548) by [cage-is](https://github.com/cage-is) - Fix testing to improve Debian integration [#549](https://github.com/thephpleague/csv/pull/549) by [David Prévot and tenzap](https://github.com/tenzap) - `Bom::tryFromSequence` and `Bom::fromSequence` supports the `Reader` and `Writer` classes. +- `ResultSet::createFromRecords` now automatically set the header for any `TabularDataReader` or `PDOStatement` instance. ### Removed diff --git a/composer.json b/composer.json index 75a29979..67bd9bc2 100644 --- a/composer.json +++ b/composer.json @@ -68,9 +68,10 @@ "test": "Runs full test suite" }, "suggest": { - "ext-iconv" : "Needed to ease transcoding CSV using iconv stream filters", "ext-dom" : "Required to use the XMLConverter and the HTMLConverter classes", - "ext-mbstring": "Needed to ease transcoding CSV using mb stream filters" + "ext-iconv" : "Needed to ease transcoding CSV using iconv stream filters", + "ext-mbstring": "Needed to ease transcoding CSV using mb stream filters", + "ext-pdo": "If you want to use the package with the PDO extension" }, "extra": { "branch-alias": { diff --git a/src/Reader.php b/src/Reader.php index ce82536c..40afb18d 100644 --- a/src/Reader.php +++ b/src/Reader.php @@ -236,7 +236,7 @@ protected function removeBOM(array $record, int $bom_length, string $enclosure): public function fetchColumn(string|int $index = 0): Iterator { - return ResultSet::createFromTabularDataReader($this)->fetchColumn($index); + return ResultSet::createFromRecords($this)->fetchColumn($index); } /** @@ -244,7 +244,7 @@ public function fetchColumn(string|int $index = 0): Iterator */ public function fetchColumnByName(string $name): Iterator { - return ResultSet::createFromTabularDataReader($this)->fetchColumnByName($name); + return ResultSet::createFromRecords($this)->fetchColumnByName($name); } /** @@ -252,12 +252,12 @@ public function fetchColumnByName(string $name): Iterator */ public function fetchColumnByOffset(int $offset = 0): Iterator { - return ResultSet::createFromTabularDataReader($this)->fetchColumnByOffset($offset); + return ResultSet::createFromRecords($this)->fetchColumnByOffset($offset); } public function value(int|string $column = 0): mixed { - return ResultSet::createFromTabularDataReader($this)->value($column); + return ResultSet::createFromRecords($this)->value($column); } /** @@ -265,7 +265,7 @@ public function value(int|string $column = 0): mixed */ public function first(): array { - return ResultSet::createFromTabularDataReader($this)->first(); + return ResultSet::createFromRecords($this)->first(); } /** @@ -273,7 +273,7 @@ public function first(): array */ public function nth(int $nth_record): array { - return ResultSet::createFromTabularDataReader($this)->nth($nth_record); + return ResultSet::createFromRecords($this)->nth($nth_record); } /** @@ -283,7 +283,7 @@ public function nth(int $nth_record): array */ public function nthAsObject(int $nth, string $className, array $header = []): ?object { - return ResultSet::createFromTabularDataReader($this)->nthAsObject($nth, $className, $header); + return ResultSet::createFromRecords($this)->nthAsObject($nth, $className, $header); } /** @@ -293,12 +293,12 @@ public function nthAsObject(int $nth, string $className, array $header = []): ?o */ public function firstAsObject(string $className, array $header = []): ?object { - return ResultSet::createFromTabularDataReader($this)->firstAsObject($className, $header); + return ResultSet::createFromRecords($this)->firstAsObject($className, $header); } public function fetchPairs($offset_index = 0, $value_index = 1): Iterator { - return ResultSet::createFromTabularDataReader($this)->fetchPairs($offset_index, $value_index); + return ResultSet::createFromRecords($this)->fetchPairs($offset_index, $value_index); } /** @@ -334,7 +334,7 @@ public function jsonSerialize(): array */ public function each(callable $callback): bool { - return ResultSet::createFromTabularDataReader($this)->each($callback); + return ResultSet::createFromRecords($this)->each($callback); } /** @@ -342,7 +342,7 @@ public function each(callable $callback): bool */ public function exists(callable $callback): bool { - return ResultSet::createFromTabularDataReader($this)->exists($callback); + return ResultSet::createFromRecords($this)->exists($callback); } /** @@ -355,7 +355,7 @@ public function exists(callable $callback): bool */ public function reduce(callable $callback, mixed $initial = null): mixed { - return ResultSet::createFromTabularDataReader($this)->reduce($callback, $initial); + return ResultSet::createFromRecords($this)->reduce($callback, $initial); } /** @@ -381,7 +381,7 @@ public function map(callable $callback): Iterator */ public function chunkBy(int $recordsCount): iterable { - return ResultSet::createFromTabularDataReader($this)->chunkBy($recordsCount); + return ResultSet::createFromRecords($this)->chunkBy($recordsCount); } /** @@ -472,12 +472,12 @@ public function matchingFirstOrFail(string $expression): TabularDataReader public function select(string|int ...$columns): TabularDataReader { - return ResultSet::createFromTabularDataReader($this)->select(...$columns); + return ResultSet::createFromRecords($this)->select(...$columns); } public function selectAllExcept(string|int ...$columns): TabularDataReader { - return ResultSet::createFromTabularDataReader($this)->selectAllExcept(...$columns); + return ResultSet::createFromRecords($this)->selectAllExcept(...$columns); } /** diff --git a/src/ResultSet.php b/src/ResultSet.php index cc031c65..ba884ecc 100644 --- a/src/ResultSet.php +++ b/src/ResultSet.php @@ -24,16 +24,20 @@ use League\Csv\Serializer\MappingFailed; use League\Csv\Serializer\TypeCastingFailed; use LimitIterator; +use PDO; +use PDOStatement; use function array_filter; use function array_flip; use function array_key_exists; +use function array_map; use function array_reduce; use function array_search; use function array_values; use function is_int; use function is_string; use function iterator_count; +use function range; /** * Represents the result set of a {@link Reader} processed by a {@link Statement}. @@ -77,31 +81,32 @@ protected function validateHeader(array $header): array }; } - public function __destruct() - { - unset($this->records); - } - - /** - * Returns a new instance from an object implementing the TabularDataReader interface. - * - * @throws SyntaxError - */ - public static function createFromTabularDataReader(TabularDataReader $reader): self - { - return new self($reader->getRecords(), $reader->getHeader()); - } - /** * Returns a new instance from a collection without header. - * - * @throws SyntaxError */ public static function createFromRecords(iterable $records = []): self { + if ($records instanceof TabularDataReader) { + return new self($records->getRecords(), $records->getHeader()); + } + + if ($records instanceof PDOStatement) { + $records->setFetchMode(PDO::FETCH_ASSOC); + + return new self(MapIterator::toIterator($records), array_map( + fn (int $i): string => $records->getColumnMeta($i)['name'], /* @phpstan-ignore-line */ + range(0, $records->columnCount() - 1) + )); + } + return new self(MapIterator::toIterator($records)); } + public function __destruct() + { + unset($this->records); + } + /** * Returns the header associated with the result set. * @@ -655,4 +660,15 @@ public function getObjects(string $className, array $header = []): Iterator { return $this->getRecordsAsObject($className, $header); } + + /** + * Returns a new instance from an object implementing the TabularDataReader interface. + * + * @throws SyntaxError + */ + #[Deprecated(message:'use League\Csv\ResultSet::createFromRecords() instead', since:'league/csv:9.22.0')] + public static function createFromTabularDataReader(TabularDataReader $reader): self + { + return self::createFromRecords($reader); + } }