Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- declare(strict_types=1);
- use Iterator;
- use SplFileObject;
- use function array_combine;
- use function array_map;
- use function strlen;
- use function trim;
- /**
- * @implements Iterator<int, mixed>
- */
- final class CsvReader implements Iterator
- {
- private const BOM = "\xef\xbb\xbf";
- private bool $skipBom = false;
- private bool $trimKeys = false;
- private bool $trimValues = false;
- /** @var string[] */
- private array $keys = [];
- public function __construct(
- private readonly SplFileObject $fileObject,
- ) {
- $this->fileObject->setFlags(SplFileObject::READ_CSV);
- }
- public function setDelimiter(string $delimiter): CsvReader
- {
- $this->fileObject->setCsvControl($delimiter);
- $this->rewind();
- return $this;
- }
- public function setSkipEmptyLines(bool $skipEmptyRows): CsvReader
- {
- $flags = SplFileObject::READ_CSV;
- if ($skipEmptyRows) {
- $flags |= SplFileObject::READ_AHEAD;
- $flags |= SplFileObject::SKIP_EMPTY;
- $flags |= SplFileObject::DROP_NEW_LINE;
- }
- $this->fileObject->setFlags($flags);
- $this->rewind();
- return $this;
- }
- public function setSkipBom(bool $skipBom): CsvReader
- {
- $this->skipBom = $skipBom;
- return $this;
- }
- public function setTrimKeys(bool $trimKeys): CsvReader
- {
- $this->trimKeys = $trimKeys;
- $this->rewind();
- return $this;
- }
- public function setTrimValues(bool $trimValues): CsvReader
- {
- $this->trimValues = $trimValues;
- $this->rewind();
- return $this;
- }
- public function rewind(): void
- {
- if ($this->skipBom) {
- $flags = $this->fileObject->getFlags();
- $this->fileObject->setFlags(0);
- $this->fileObject->rewind();
- $potentialBom = $this->fileObject->fread(strlen(self::BOM));
- $this->fileObject->setFlags($flags);
- if ($potentialBom !== self::BOM) {
- $this->fileObject->rewind();
- }
- } else {
- $this->fileObject->rewind();
- }
- /** @var array<string> $keys */
- $keys = $this->fileObject->current();
- $this->keys = $this->trimKeys ? array_map('trim', $keys) : $keys;
- $this->fileObject->next();
- }
- public function valid(): bool
- {
- return $this->fileObject->valid();
- }
- /**
- * @return array<string, mixed>
- */
- public function current(): array
- {
- /** @var array<string> $values */
- $values = $this->fileObject->current();
- if ($this->trimValues) {
- $values = array_map('trim', $values);
- }
- return array_combine($this->keys, $values);
- }
- public function key(): int
- {
- return $this->fileObject->key() + 1;
- }
- public function next(): void
- {
- $this->fileObject->next();
- }
- }
- // Example:
- // First create a temporary CSV file for demo purposes
- $data = [
- ['Firstname', 'Lastname', 'Email'],
- ];
- $tempFile = new SplTempFileObject();
- foreach ($data as $fields) {
- $tempFile->fputcsv($fields);
- }
- // Then read the file and dump the records
- $csvReader = (new CsvReader($tempFile))
- ->setDelimiter(',')
- ->setSkipEmptyLines(true)
- ->setTrimKeys(true)
- ->setTrimValues(true);
- foreach ($csvReader as $row) {
- var_dump($row);
- }
- // Output
- //
- // array(3) {
- // ["Firstname"] => string(4) "John"
- // ["Lastname"] => string(3) "Doe"
- // ["Email"] => string(20) "[email protected]"
- // }
- //
- // array(3) {
- // ["Firstname"] => string(4) "Jane"
- // ["Lastname"] => string(3) "Doe"
- // ["Email"] => string(20) "[email protected]"
- // }
Advertisement
Add Comment
Please, Sign In to add comment