PHPackages                             ajgl/csv-rfc - 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. ajgl/csv-rfc

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

ajgl/csv-rfc
============

Drop in replacement for native PHP CSV related functions to read and/or write RFC4180 compliant CSV files

0.4.0(5y ago)18384.7k—0.9%3[1 issues](https://github.com/ajgarlag/AjglCsvRfc/issues)4MITPHPPHP ^7.3 || ^8.0

Since Feb 25Pushed 5y ago2 watchersCompare

[ Source](https://github.com/ajgarlag/AjglCsvRfc)[ Packagist](https://packagist.org/packages/ajgl/csv-rfc)[ Docs](https://github.com/ajgarlag/AjglCsvRfc)[ RSS](/packages/ajgl-csv-rfc/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (4)Dependencies (3)Versions (5)Used By (4)

AjglCsvRfc
==========

[](#ajglcsvrfc)

The AjglCsvRfc component offers a drop in replacement for native PHP CSV related functions to read and/or write RFC4180 compliant CSV files.

[![Build Status](https://github.com/ajgarlag/AjglCsvRfc/workflows/test/badge.svg?branch=master)](https://github.com/ajgarlag/AjglCsvRfc/actions)[![Latest Stable Version](https://camo.githubusercontent.com/75dfcfd870714b992ec7cb98d6bcba21a1ad6b3b830085a12a1eab4649a09014/68747470733a2f2f706f7365722e707567782e6f72672f616a676c2f6373762d7266632f762f737461626c652e706e67)](https://packagist.org/packages/ajgl/csv-rfc)[![Latest Unstable Version](https://camo.githubusercontent.com/9654bdb3518034852a55a2bdbe29e99207310ff3188b0a5d826e91e7bbb9e75b/68747470733a2f2f706f7365722e707567782e6f72672f616a676c2f6373762d7266632f762f756e737461626c652e706e67)](https://packagist.org/packages/ajgl/csv-rfc)[![Total Downloads](https://camo.githubusercontent.com/9bec462146a696dd1c9d65dbd9421db22cfa089e07b3d2d0cd5b5bd884327996/68747470733a2f2f706f7365722e707567782e6f72672f616a676c2f6373762d7266632f646f776e6c6f6164732e706e67)](https://packagist.org/packages/ajgl/csv-rfc)[![Montly Downloads](https://camo.githubusercontent.com/b680621cb093df3c01ca4fe25728cd38c9c5491e682145dc1bd0c752323c87d5/68747470733a2f2f706f7365722e707567782e6f72672f616a676c2f6373762d7266632f642f6d6f6e74686c792e706e67)](https://packagist.org/packages/ajgl/csv-rfc)[![Daily Downloads](https://camo.githubusercontent.com/ffe43feae1e7cf557b01dee5ee01844f13b362947729e3a671cf2ff98380e63b/68747470733a2f2f706f7365722e707567782e6f72672f616a676c2f6373762d7266632f642f6461696c792e706e67)](https://packagist.org/packages/ajgl/csv-rfc)[![License](https://camo.githubusercontent.com/78b42f0196227584ad7f35c13f23d0bf528bf5545a942e99a5e677454e14b9f2/68747470733a2f2f706f7365722e707567782e6f72672f616a676c2f6373762d7266632f6c6963656e73652e706e67)](https://packagist.org/packages/ajgl/csv-rfc)[![SensioLabsInsight](https://camo.githubusercontent.com/26c3697a865ec7976d914f657cc3ec27cb4721ea912537e620a101cca2ba4215/68747470733a2f2f696e73696768742e73656e73696f6c6162732e636f6d2f70726f6a656374732f37323138646562632d366330372d346136302d396230622d6530383130336331653062322f6d696e692e706e67)](https://insight.sensiolabs.com/projects/7218debc-6c07-4a60-9b0b-e08103c1e0b2)

The native PHP implementation contains a *Wont fix* bug [\#50686](https://bugs.php.net/bug.php?id=50686) when you try to write a CSV field which contains the escape char (`\` by default), followed by the enclosure char (`"` by default).

The [RFC 4180](https://tools.ietf.org/html/rfc4180) states that:

> If double-quotes are used to enclose fields, then a double-quote appearing inside a field must be escaped by preceding it with another double quote.

The CSV version of the string `"Hello\", World!` should be `"""Hello\"", World!"` but it does not work as expected. You can see a detailed explanation at

This package provides an alternative implementation to read and write well escaped CSV files for the following functions and methods:

NativeAlternative`fgetcsv``Ajgl\Csv\Rfc\fgetcsv``fputcsv``Ajgl\Csv\Rfc\fputcsv``str_getcsv``Ajgl\Csv\Rfc\str_getcsv``SplFileObject::fgetcsv``Ajgl\Csv\Rfc\Spl\SplFileObject::fgetcsv``SplFileObject::fputcsv``Ajgl\Csv\Rfc\Spl\SplFileObject::fputcsv``SplFileObject::setCsvControl``Ajgl\Csv\Rfc\Spl\SplFileObject::setCsvControl`Installation
------------

[](#installation)

To install the latest stable version of this component, open a console and execute the following command:

```
$ composer require ajgl/csv-rfc

```

Usage
-----

[](#usage)

### Alternative functions

[](#alternative-functions)

The simplest way to use this library is to call the alternative CSV functions:

```
use Ajgl\Csv\Rfc;

$handler = fopen('php://temp', 'w+');
Rfc\fputcsv($handler, array('Hello \"World"!'));
rewind($handler);
$row = Rfc\fgetcsv($handler);
rewind($handler);
$row = Rfc\str_getcsv(fgets($handler));
```

### Alternative clases

[](#alternative-clases)

If you prefer you can use the alternative implementation for `SplFileObject` or `SplTempFileObject`:

```
use Ajgl\Csv\Rfc;

$file = new Rfc\Spl\SplFileObject('php://temp', 'w+');
$file->fputcsv(array('Hello \"World"!'));
$file->rewind();
$row = $file->fgetcsv();
$file->rewind();
$file->setFlags(\SplFileObject::READ_CSV | \SplFileObject::READ_AHEAD | \SplFileObject::SKIP_EMPTY);
foreach ($file as $line) {
    $row = $line;
}
```

### Stream filter

[](#stream-filter)

Instead of using the alternative functions or classes, you can use the provided stream filter to fix the enclosure escape. You must register the stream filter (if not registered yet) and append it to your stream:

```
use Ajgl\Csv\Rfc;

Rfc\CsvRfcWriteStreamFilter::register();

$handler = fopen('php://temp', 'w+');
stream_filter_append(
    $handler,
    Rfc\CsvRfcWriteStreamFilter::FILTERNAME_DEFAULT,
    STREAM_FILTER_WRITE
);
fputcsv($handler, array('Hello \"World"!'));
rewind($handler);
$row = fgetcsv($handler, 0, ',', '"', '"');
```

**❮ NOTE ❯**: The `$escape_char` in [fputcsv](http://php.net/manual/en/function.fputcsv.php) MUST be (if allowed) the default one (the backslash `\`). The `$enclosure`and `$escape` parameters in [fgetcsv](http://php.net/manual/en/function.fgetcsv.php) MUST be equals.

#### Custom enclosure character

[](#custom-enclosure-character)

By default, the enclosure character of the stream filter is a double-quote (`"`). If you want to change it, you can provide a custom enclosure character in two different ways.

##### Via filter params

[](#via-filter-params)

An array with an `enclosure` key can be provided when appending the filter to the stream:

```
use Ajgl\Csv\Rfc;

$enclosure = '@';
Rfc\CsvRfcWriteStreamFilter::register();

$handler = fopen('php://temp', 'w+');
stream_filter_append(
    $handler,
    Rfc\CsvRfcWriteStreamFilter::FILTERNAME_DEFAULT,
    STREAM_FILTER_WRITE,
    array(
        'enclosure' => $enclosure
    )
);
fputcsv($handler, array('Hello \"World"!'), ',', '@');
rewind($handler);
$row = fgetcsv($handler, 0, ',', '@', '@');
```

##### Via filter name

[](#via-filter-name)

If the filter name starts with the special key `csv.rfc.write.` you can define your custom enclosure character appending it to the filtername:

```
use Ajgl\Csv\Rfc;

$enclosure = '@';
$filtername = 'csv.rfc.write.' . $enclosure;
Rfc\CsvRfcWriteStreamFilter::register($filtername);

$handler = fopen('php://temp', 'w+');
stream_filter_append(
    $handler,
    $filtername,
    STREAM_FILTER_WRITE
);
fputcsv($handler, array('Hello \"World"!'), ',', '@');
rewind($handler);
$row = fgetcsv($handler, 0, ',', '@', '@');
```

**❮ NOTE ❯**: The enclosure character passed via parameters will override the one defined via filter name.

### End of line (EOL)

[](#end-of-line-eol)

#### Writing CSV

[](#writing-csv)

By default, the PHP CSV implementation uses `LF` (`"\n"`) as EOL while writing a CSV row. These alternative functions use `LF` (`"\n"`) by default too.

But, the RFC 4180 states that:

> Each record is located on a separate line, delimited by a line break (CRLF).

So, if you want to write RFC4180 compliant CSV, you can override the default EOL using:

```
use Ajgl\Csv\Rfc\CsvRfcUtils;

CsvRfcUtils::setDefaultWriteEol(CsvRfcUtils::EOL_WRITE_RFC);
```

#### Reading CSV

[](#reading-csv)

To read the CSV data, this implementation leverages the PHP native capabilities to read files. If you are having any problem with the EOL detection, you should enable the `auto_detect_line_endings` configuration option as following the PHP doc [recomendation](https://secure.php.net/manual/en/filesystem.configuration.php#ini.auto-detect-line-endings).

```
ini_set('ini.auto-detect-line-endings', true);
```

### Integration with `league/csv isActiveStreamFilter()) {
    throw new \Exception("The Stream Filter API is not active.");
}
$writer->appendStreamFilter(CsvRfcWriteStreamFilter::FILTERNAME_DEFAULT);
$writer->insertOne(array('"Hello\", World!'));
```

**❮ NOTE ❯**: Do not override the default writer escape character (`\`).

##### Known limitations

[](#known-limitations)

- The `league/csv` package does not support the Stream Filter API when the writer instance is created from a `SplFileObject`.
- The `league/csv` implementation will always leverage the standard `\SplFileObject::fputcsv` to write CSV data, so the fix to write [RFC 4180](https://tools.ietf.org/html/rfc4180) compatible files from `Ajgl\Csv\Rfc\Spl\SplFileObject::fputcsv` will be ignored.

#### Reader Integration

[](#reader-integration)

To read back the CSV data, you can leverage the standard implementation, but you MUST set the reader escape and enclosure characters to the same value.

```
use League\Csv\Reader;

$reader = Reader::createFromPath('/tmp/foobar.csv');
$reader->setEscape($reader->getEnclosure());
foreach ($reader as $row) {
    //...
}
```

License
-------

[](#license)

This component is under the MIT license. See the complete license in the [LICENSE](LICENSE) file.

Reporting an issue or a feature request
---------------------------------------

[](#reporting-an-issue-or-a-feature-request)

Issues and feature requests are tracked in the [Github issue tracker](https://github.com/ajgarlag/AjglCsvRfc/issues).

Author Information
------------------

[](#author-information)

Developed with ♥ by [Antonio J. García Lagar](http://aj.garcialagar.es).

If you find this component useful, please add a ★ in the [GitHub repository page](https://github.com/ajgarlag/AjglCsvRfc) and/or the [Packagist package page](https://packagist.org/packages/ajgl/csv-rfc).

###  Health Score

39

—

LowBetter than 86% of packages

Maintenance19

Infrequent updates — may be unmaintained

Popularity44

Moderate usage in the ecosystem

Community18

Small or concentrated contributor base

Maturity61

Established project with proven stability

 Bus Factor1

Top contributor holds 92% 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 ~585 days

Total

4

Last Release

1979d ago

PHP version history (2 changes)0.1.0PHP &gt;=5.4.0

0.4.0PHP ^7.3 || ^8.0

### Community

Maintainers

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

---

Top Contributors

[![ajgarlag](https://avatars.githubusercontent.com/u/388184?v=4)](https://github.com/ajgarlag "ajgarlag (23 commits)")[![kumamidori](https://avatars.githubusercontent.com/u/384567?v=4)](https://github.com/kumamidori "kumamidori (2 commits)")

---

Tags

csvrfc4180rfc4180

###  Code Quality

TestsPHPUnit

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/ajgl-csv-rfc/health.svg)

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

###  Alternatives

[maatwebsite/excel

Supercharged Excel exports and imports in Laravel

12.7k144.3M712](/packages/maatwebsite-excel)[league/csv

CSV data manipulation made easy in PHP

3.5k166.1M646](/packages/league-csv)[rap2hpoutre/fast-excel

Fast Excel import/export for Laravel

2.3k24.9M47](/packages/rap2hpoutre-fast-excel)[openspout/openspout

PHP Library to read and write spreadsheet files (CSV, XLSX and ODS), in a fast and scalable way

1.2k57.6M131](/packages/openspout-openspout)[goodby/csv

CSV import/export library

9555.6M23](/packages/goodby-csv)[sonata-project/exporter

Lightweight Exporter library

44920.9M35](/packages/sonata-project-exporter)

PHPackages © 2026

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