Skip to content

Commit 4f1c2e0

Browse files
committed
Refactor SplCsvReader to improve record reading logic and ensure valid records are processed correctly
1 parent e53f458 commit 4f1c2e0

File tree

1 file changed

+45
-11
lines changed

1 file changed

+45
-11
lines changed

src/Readers/SplCsvReader.php

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -239,28 +239,62 @@ public function nextRecord(): array|false
239239
}
240240

241241
try {
242-
// For the first read, position the reader correctly
242+
// Position the reader at the correct record
243243
if ($this->position === -1) {
244-
$reader->rewind();
244+
// First read - start from beginning
245245
if ($this->getConfig()->hasHeader()) {
246-
$reader->current(); // Read header
247-
$reader->next(); // Move past header
246+
// Cache header first
247+
if ($this->header === null) {
248+
$reader->rewind();
249+
$headerRecord = $reader->current();
250+
if ($headerRecord !== false && $headerRecord !== [null] && is_array($headerRecord) && ! $this->isInvalidRecord($headerRecord)) {
251+
$this->header = $headerRecord;
252+
}
253+
}
254+
// Now seek to first data record (line 1)
255+
$reader->seek(1);
256+
} else {
257+
// No header, start at beginning
258+
$reader->rewind();
248259
}
260+
// Reader is now positioned at the first data record
249261
} else {
250-
// For subsequent reads, just advance sequentially (much faster than seek)
262+
// Subsequent reads - advance to next record
251263
$reader->next();
252264
}
253265

254-
$record = $reader->current();
266+
// Read records until we find a valid one
267+
do {
268+
$record = $reader->current();
255269

256-
if ($record === false || $record === null || ! is_array($record) || $this->isInvalidRecord($record)) {
257-
return false;
258-
}
270+
if ($record === false) {
271+
return false;
272+
}
273+
274+
// Ensure we have a valid array record
275+
if (! is_array($record)) {
276+
$reader->next();
277+
$nextPosition++;
278+
279+
continue; // skip non-array data
280+
}
281+
282+
if ($this->isInvalidRecord($record)) {
283+
$reader->next();
284+
$nextPosition++;
285+
286+
continue; // skip invalid record
287+
}
288+
289+
break; // valid record found
290+
} while (true);
259291

260-
// Update position only after successful read
261292
$this->position = $nextPosition;
262-
$this->cachedRecord = $record; // Cache the record
263293

294+
/** @var array $record */
295+
$this->cachedRecord = $record;
296+
297+
/** @var array $record */
264298
return $record;
265299
} catch (Exception) {
266300
return false;

0 commit comments

Comments
 (0)