PHPackages                             philiprehberger/php-csv - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [PDF &amp; Document Generation](/categories/documents)
4. /
5. philiprehberger/php-csv

ActiveLibrary[PDF &amp; Document Generation](/categories/documents)

philiprehberger/php-csv
=======================

Memory-efficient CSV reader and writer with header mapping and type casting

v1.4.0(4mo ago)168MITPHPPHP ^8.2CI passing

Since Mar 15Pushed 1mo agoCompare

[ Source](https://github.com/philiprehberger/php-csv)[ Packagist](https://packagist.org/packages/philiprehberger/php-csv)[ Docs](https://github.com/philiprehberger/php-csv)[ GitHub Sponsors](https://github.com/philiprehberger)[ RSS](/packages/philiprehberger-php-csv/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (6)Versions (10)Used By (0)

PHP CSV
=======

[](#php-csv)

[![Tests](https://github.com/philiprehberger/php-csv/actions/workflows/tests.yml/badge.svg)](https://github.com/philiprehberger/php-csv/actions/workflows/tests.yml)[![Latest Version on Packagist](https://camo.githubusercontent.com/a4b96e43d0c16301107b18b33f7dd1406dbd08e3eb8ecfac50fb2ea754eb6a10/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7068696c69707265686265726765722f7068702d6373762e737667)](https://packagist.org/packages/philiprehberger/php-csv)[![Last updated](https://camo.githubusercontent.com/a41b86555d47b97f1738dfbdf8edb626de69d1065898212e317a92423100b562/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f7068696c69707265686265726765722f7068702d637376)](https://github.com/philiprehberger/php-csv/commits/main)

Memory-efficient CSV reader and writer with header mapping and type casting.

Requirements
------------

[](#requirements)

- PHP 8.2+

Installation
------------

[](#installation)

```
composer require philiprehberger/php-csv
```

Usage
-----

[](#usage)

### Reading a CSV file

[](#reading-a-csv-file)

```
use PhilipRehberger\Csv\Csv;

// Read from file with headers
$rows = Csv::read('data.csv')->toArray();
// [['name' => 'Alice', 'age' => '30'], ...]

// Read from string
$rows = Csv::readString($csvContent)->toArray();
```

### Generator-based iteration

[](#generator-based-iteration)

The reader uses PHP generators for memory-efficient processing of large files:

```
foreach (Csv::read('large-file.csv') as $row) {
    // Process one row at a time — constant memory usage
}
```

### Type casting

[](#type-casting)

Automatically detect and cast value types:

```
$rows = Csv::read('data.csv')
    ->castTypes(true)
    ->toArray();
// "42" -> int, "3.14" -> float, "true"/"false" -> bool, "" -> null
```

### Filtering and mapping

[](#filtering-and-mapping)

```
$rows = Csv::read('data.csv')
    ->castTypes(true)
    ->filter(fn (array $row) => $row['age'] >= 18)
    ->map(fn (array $row) => [...$row, 'label' => strtoupper($row['name'])])
    ->toArray();
```

### Row Validation

[](#row-validation)

Validate each row during reading. Invalid rows are skipped and errors are collected:

```
$reader = Csv::read('data.csv')
    ->validate(fn (array $row) => isset($row['email']) && str_contains($row['email'], '@'));

$rows = $reader->toArray();

// Inspect which rows failed validation
foreach ($reader->getValidationErrors() as $error) {
    echo "Row {$error['row']}: {$error['error']}\n";
}
```

The validator can also throw an exception to provide a specific error message:

```
$reader = Csv::read('data.csv')
    ->validate(function (array $row) {
        if (empty($row['name'])) {
            throw new \InvalidArgumentException('Name is required');
        }
        return true;
    });
```

### Progress Tracking

[](#progress-tracking)

Monitor processing progress with a callback invoked after each row:

```
Csv::read('large-file.csv')
    ->withProgress(function (int $rowNumber) {
        if ($rowNumber % 1000 === 0) {
            echo "Processed {$rowNumber} rows...\n";
        }
    })
    ->each(fn (array $row) => processRow($row));
```

### First and last rows

[](#first-and-last-rows)

Quickly access the first or last data row without loading everything into an array:

```
$first = Csv::read('data.csv')->firstRow();
// ['name' => 'Alice', 'age' => '30', ...]

$last = Csv::read('data.csv')->lastRow();
// ['name' => 'Zoe', 'age' => '28', ...]
```

Both methods return `null` if the CSV has no data rows.

### Grouping rows

[](#grouping-rows)

Group rows by a column value into an associative array:

```
$groups = Csv::read('data.csv')->groupBy('city');
// ['Berlin' => [['name' => 'Alice', ...], ...], 'Vienna' => [...]]
```

### Column transformation

[](#column-transformation)

Apply per-column transformations during reading:

```
$rows = Csv::read('data.csv')
    ->transformColumn('name', fn (string $value) => strtoupper($value))
    ->transformColumn('age', fn (string $value) => (int) $value)
    ->toArray();
```

### Duplicate detection

[](#duplicate-detection)

Find duplicate rows based on specific columns:

```
$duplicates = Csv::read('data.csv')->detectDuplicates(['email']);
// [2, 5] — 0-based indices of duplicate rows
```

### Custom delimiters

[](#custom-delimiters)

```
$rows = Csv::readString($tsv)
    ->delimiter("\t")
    ->toArray();
```

### TSV and PSV convenience methods

[](#tsv-and-psv-convenience-methods)

```
// Tab-separated values
$rows = Csv::readTsv('data.tsv')->toArray();
$tsv = Csv::writeTsv()->headers(['name', 'age'])->rows($data)->toString();

// Pipe-separated values
$rows = Csv::readPsv('data.psv')->toArray();
$psv = Csv::writePsv()->headers(['name', 'age'])->rows($data)->toString();
```

### Writing CSV

[](#writing-csv)

```
use PhilipRehberger\Csv\Csv;

Csv::write('output.csv')
    ->headers(['name', 'age', 'city'])
    ->row(['name' => 'Alice', 'age' => 30, 'city' => 'Berlin'])
    ->row(['name' => 'Bob', 'age' => 25, 'city' => 'Vienna'])
    ->save();

// Or get as string
$csv = Csv::write('')
    ->headers(['name', 'age'])
    ->rows($data)
    ->toString();
```

### Streaming Writer

[](#streaming-writer)

Write rows directly to disk without buffering, ideal for very large files:

```
use PhilipRehberger\Csv\Csv;

$writer = Csv::streamWrite('large-output.csv');
$writer->writeHeader(['id', 'name', 'value']);

foreach ($dataSource as $record) {
    $writer->writeRow([$record->id, $record->name, $record->value]);
}

$writer->close();
```

### Appending to an existing file

[](#appending-to-an-existing-file)

Append rows to an existing CSV without writing headers again:

```
Csv::write('output.csv')
    ->headers(['name', 'age'])
    ->row(['name' => 'Charlie', 'age' => 35])
    ->appendToFile('output.csv');
```

### BOM for Excel

[](#bom-for-excel)

Prepend a UTF-8 BOM for Excel compatibility:

```
Csv::write('output.csv')
    ->headers(['name', 'age'])
    ->rows($data)
    ->bom(true)
    ->save();
```

API
---

[](#api)

### `Csv` (static entry)

[](#csv-static-entry)

MethodDescription`Csv::read(string $path): CsvReader`Create a reader from a file path`Csv::readString(string $content): CsvReader`Create a reader from a string`Csv::readTsv(string $path): CsvReader`Create a TSV reader from a file path`Csv::readPsv(string $path): CsvReader`Create a PSV reader from a file path`Csv::write(string $path): CsvWriter`Create a writer for a file path`Csv::writeTsv(): CsvWriter`Create a TSV writer`Csv::writePsv(): CsvWriter`Create a PSV writer`Csv::streamWrite(string $path, string $delimiter = ','): StreamingWriter`Create a streaming writer for a file path### `CsvReader`

[](#csvreader)

MethodDescription`delimiter(string $char): self`Set the field delimiter (default `,`)`enclosure(string $char): self`Set the field enclosure (default `"`)`escape(string $char): self`Set the field escape character (default `\`)`hasHeader(bool $flag): self`Whether the first row is a header (default `true`)`skipEmpty(bool $flag): self`Skip empty rows (default `true`)`castTypes(bool $flag): self`Auto-detect types: int, float, bool, null`filter(callable $fn): self`Filter rows by a predicate`map(callable $fn): self`Transform each row`validate(callable $fn): self`Validate rows; invalid ones are skipped`transformColumn(string $column, callable $fn): self`Apply a transformer to a specific column`detectDuplicates(array $columns): array`Return 0-based indices of duplicate rows`withProgress(callable $fn): self`Set a progress callback (receives row number)`getValidationErrors(): array`Get errors from the last read`each(callable $fn): void`Execute a callback for each row`toArray(): array`Collect all rows into an array`firstRow(): ?array`Return the first data row or null`lastRow(): ?array`Return the last data row or null`groupBy(string $column): array`Group rows by a column value`count(): int`Count the number of rows### `CsvWriter`

[](#csvwriter)

MethodDescription`headers(array $headers): self`Set column headers`row(array $row): self`Add a single row`rows(array $rows): self`Add multiple rows`delimiter(string $char): self`Set the field delimiter (default `,`)`enclosure(string $char): self`Set the field enclosure (default `"`)`escape(string $char): self`Set the field escape character (default `\`)`bom(bool $flag): self`Prepend UTF-8 BOM for Excel`appendToFile(string $path): self`Append rows to an existing file (no headers)`save(): void`Write to the configured file path`toString(): string`Return the CSV as a string### `StreamingWriter`

[](#streamingwriter)

MethodDescription`enclosure(string $char): self`Set the field enclosure (default `"`)`escape(string $char): self`Set the field escape character (default `\`)`writeHeader(array $headers): void`Write the header row`writeRow(array $row): void`Write a single data row`writeRows(array $rows): void`Write multiple data rows`isHeaderWritten(): bool`Whether the header has been written`close(): void`Close the file handleDevelopment
-----------

[](#development)

```
composer install
vendor/bin/phpunit
vendor/bin/pint --test
vendor/bin/phpstan analyse
```

Support
-------

[](#support)

If you find this project useful:

⭐ [Star the repo](https://github.com/philiprehberger/php-csv)

🐛 [Report issues](https://github.com/philiprehberger/php-csv/issues?q=is%3Aissue+is%3Aopen+label%3Abug)

💡 [Suggest features](https://github.com/philiprehberger/php-csv/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement)

❤️ [Sponsor development](https://github.com/sponsors/philiprehberger)

🌐 [All Open Source Projects](https://philiprehberger.com/open-source-packages)

💻 [GitHub Profile](https://github.com/philiprehberger)

🔗 [LinkedIn Profile](https://www.linkedin.com/in/philiprehberger)

License
-------

[](#license)

[MIT](LICENSE)

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance84

Actively maintained with recent releases

Popularity10

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 89.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~2 days

Total

9

Last Release

124d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/cfd7d24cbbf32400fa13ce0bbe7a31edd2d66a6d4488eafdb3d64c5337bf0435?d=identicon)[philiprehberger](/maintainers/philiprehberger)

---

Top Contributors

[![philiprehberger](https://avatars.githubusercontent.com/u/8218077?v=4)](https://github.com/philiprehberger "philiprehberger (17 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (2 commits)")

---

Tags

parsergeneratorcsvwriterreadertype-casting

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/philiprehberger-php-csv/health.svg)

```
[![Health](https://phpackages.com/badges/philiprehberger-php-csv/health.svg)](https://phpackages.com/packages/philiprehberger-php-csv)
```

###  Alternatives

[shuchkin/simplexlsx

Parse and retrieve data from Excel XLSx files. MS Excel 2007 workbooks PHP reader.

1.8k4.3M35](/packages/shuchkin-simplexlsx)[faisalman/simple-excel-php

Easily parse / convert / write between Microsoft Excel XML / CSV / TSV / HTML / JSON / etc formats

557614.2k1](/packages/faisalman-simple-excel-php)[shuchkin/simplexlsxgen

Export data to Excel XLSx file. PHP XLSX generator.

1.1k2.5M40](/packages/shuchkin-simplexlsxgen)[avadim/fast-excel-reader

Lightweight and very fast XLSX Excel Spreadsheet and CSV Reader in PHP

105786.0k14](/packages/avadim-fast-excel-reader)[csanquer/colibri-csv

Lightweight and performant CSV reader and writer library

16165.7k5](/packages/csanquer-colibri-csv)[rodenastyle/stream-parser

PHP Multiformat Streaming Parser

442206.4k2](/packages/rodenastyle-stream-parser)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
