From 8cc9dd8cec9891e974ca61c71372d78e5e100bf6 Mon Sep 17 00:00:00 2001 From: ignace nyamagana butera Date: Fri, 6 Dec 2024 11:59:43 +0100 Subject: [PATCH] Improve Writer speed by precalculating the insert method --- src/Writer.php | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/Writer.php b/src/Writer.php index 45b07e54..739b1047 100644 --- a/src/Writer.php +++ b/src/Writer.php @@ -13,6 +13,7 @@ namespace League\Csv; +use Closure; use Deprecated; use function array_map; @@ -40,6 +41,8 @@ class Writer extends AbstractCsv implements TabularDataWriter protected bool $enclose_all = false; /** @var array{0:array,1:array} */ protected array $enclosure_replace = [[], []]; + /** @var Closure(array): (int|false) */ + protected Closure $insertRecord; protected function resetProperties(): void { @@ -49,6 +52,17 @@ protected function resetProperties(): void [$this->enclosure, $this->escape.$this->enclosure.$this->enclosure], [$this->enclosure.$this->enclosure, $this->escape.$this->enclosure], ]; + + $this->insertRecord = fn (array $record): int|false => match ($this->enclose_all) { + true => $this->document->fwrite(implode( + $this->delimiter, + array_map( + fn ($content) => $this->enclosure.$content.$this->enclosure, + str_replace($this->enclosure_replace[0], $this->enclosure_replace[1], $record) + ) + ).$this->newline), + false => $this->document->fputcsv($record, $this->delimiter, $this->enclosure, $this->escape, $this->newline), + }; } /** @@ -106,21 +120,10 @@ public function insertAll(iterable $records): int */ public function insertOne(array $record): int { - $insert = fn (array $record): int|false => match (true) { - $this->enclose_all => $this->document->fwrite(implode( - $this->delimiter, - array_map( - fn ($content) => $this->enclosure.$content.$this->enclosure, - str_replace($this->enclosure_replace[0], $this->enclosure_replace[1], $record) - ) - ).$this->newline), - default => $this->document->fputcsv($record, $this->delimiter, $this->enclosure, $this->escape, $this->newline), - }; - $record = array_reduce($this->formatters, fn (array $record, callable $formatter): array => $formatter($record), $record); $this->validateRecord($record); set_error_handler(fn (int $errno, string $errstr, string $errfile, int $errline) => true); - $bytes = $insert($record); + $bytes = ($this->insertRecord)($record); restore_error_handler(); if (false === $bytes) { throw CannotInsertRecord::triggerOnInsertion($record); @@ -204,6 +207,7 @@ public function setFlushThreshold(?int $threshold): self public function relaxEnclosure(): self { $this->enclose_all = false; + $this->resetProperties(); return $this; } @@ -211,6 +215,7 @@ public function relaxEnclosure(): self public function forceEnclosure(): self { $this->enclose_all = true; + $this->resetProperties(); return $this; }