Last active
August 2, 2023 11:57
-
-
Save tezvi/a598b98eeaad1701a4b65bee96953295 to your computer and use it in GitHub Desktop.
CSV reader class that supports mapping columns with custom names.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* CSV reader class that supports mapping columns with custom names. | |
* | |
* @author Andrej Vitez <[email protected]> | |
*/ | |
class CsvReader implements Iterator { | |
private string $filePath; | |
private array $columns = []; | |
private SplFileObject $file; | |
private ?array $currentRow = null; | |
/** | |
* @param string $filePath CSV file path. | |
* @param array $columns Array of column names indexed by key names. | |
* @param bool $firstRowHeaders If true first row will be skipped from iteration. | |
* @param string $delimiter Delimiter to be used when parsing CSV, default is semicolon. | |
* @param string $enclosure Character that encapsulates column value, default is double quote. | |
* @param string $escape Character used for escaping sequence, default is backslash. | |
*/ | |
public function __construct( | |
string $filePath, | |
array $columns = [], | |
bool $firstRowHeaders = false, | |
string $delimiter = ';', | |
string $enclosure = '"', | |
string $escape = '\\' | |
) { | |
if (!is_readable($filePath)) { | |
throw new RuntimeException("CSV file '$filePath' is not readable"); | |
} | |
$this->filePath = $filePath; | |
$this->columns = $columns; | |
$this->firstRowHeaders = $firstRowHeaders; | |
$this->file = new SplFileObject($this->filePath, 'r'); | |
$this->file->setFlags(SplFileObject::READ_CSV); | |
$this->file->setCsvControl($delimiter, $enclosure, $escape); | |
$this->file->setFlags(SplFileObject::READ_CSV | SplFileObject::READ_AHEAD | SplFileObject::SKIP_EMPTY); | |
} | |
public function setColumnNames(array $columns): void { | |
$this->columns = $columns; | |
} | |
public function key(): ?int { | |
return $this->file->key(); | |
} | |
public function rewind(): void { | |
$this->file->rewind(); | |
$this->readRow(); | |
if ($this->firstRowHeaders) { | |
$this->readRow(); | |
} | |
} | |
private function readRow(): void { | |
$row = $this->file->current(); | |
if (count($this->columns)) { | |
$this->currentRow = array_combine($this->columns, $row); | |
} else { | |
$this->currentRow = $row; | |
} | |
$this->file->next(); | |
} | |
public function current(): ?array { | |
return $this->currentRow; | |
} | |
public function next(): void { | |
$this->readRow(); | |
} | |
public function valid(): bool { | |
while ($this->currentRow !== false && $this->isEmptyRow()) { | |
$this->next(); | |
} | |
return $this->currentRow !== false; | |
} | |
private function isEmptyRow(): bool { | |
foreach ($this->currentRow as $cell) { | |
if (!empty(trim($cell))) { | |
return false; | |
} | |
} | |
return true; | |
} | |
public function __destruct() { | |
$this->close(); | |
} | |
public function close(): void { | |
unset($this->file); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment