Library / SDK
thephpleague/csv avatar
thephpleague/csv

League CSV: the support table names version 9.29.0 while the newest release is 9.28.0

CSV data manipulation made easy in PHP

3,479 stars356 forksPHPMIT

At a glance

What is it?
League CSV reads, writes and filters CSV in PHP with one extension requirement and a single composer command. Its compatibility table jumps ahead of its own release history, its configuration section is two forward-looking deprecation warnings, and the one setting with code attached is for legacy Macintosh line endings.
Who is it for?
Adequate fit: a PHP project that has to read or write CSV larger than memory, wants array to object mapping and format conversion without pulling in a framework, and can pin a minor version.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • thephpleague/csv3,479 ★ · -4
Star history
Repository2026-09-242026-11-14
thephpleague/csv3.5k3.5k

-4 Stars in the last 51 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The support table's last row is 9.29.0, ahead of the 9.28.0 release

The system requirements section is where this project is most concrete, and where it is most surprising. There is one extension requirement, ext-filter, and a recommendation to use the latest stable PHP. After that comes a table of PHP support for version 9 of the library, and its last row reads 9.29.0 with a minimum of PHP 8.2.0 and a maximum of PHP 8.x. The newest published release is 9.28.0. So the table documents a version of the library that has no release behind it, which means the compatibility guidance and the release history are maintained separately and one of them is ahead.

The row above it is 9.16.0, at a minimum of PHP 8.1.2 and a maximum of PHP 8.x. Two rows back is 9.9.0, which caps at PHP 8.3.x. Before that the caps are tight: 9.8.0 and 9.7.3 stop at PHP 8.1.x, 9.7.0 and 9.6.2 stop at 8.0.x, and the three earliest rows stop at 7.1.x, 7.2.x and 7.4.x. The ceiling has been lifted in only the two newest rows, and both of them say PHP 8.x with no upper bound at all.

Eleven rows cover a version line, and the install constraint permits any of it

Read the table as gaps rather than as rows. It names 9.0.0, then 9.1.2, then 9.2.0, then jumps to 9.6.0. So three releases of the 9.x line have no compatibility statement. From 9.9.0 the next named version is 9.16.0, leaving six unstated. From 9.16.0 it jumps to 9.29.0, leaving twelve. Eleven rows therefore stand in for a line that has already reached 9.28.0.

What a reader does with that depends on the constraint they install with. The install section gives one command:

bash
composer require league/csv:^9.0

A caret on 9.0 permits any 9.x the resolver considers compatible with the PHP in use, which is what makes the table useful rather than decorative. It also means the minimum PHP of the resolved version is decided by the resolver and not by the reader, so a project on an older runtime can end up with a library whose own floor is PHP 8.2. The one hard extension requirement, ext-filter, is separate from all of this and is the same on every row.

The configuration section is two forward-looking deprecation warnings

There is no configuration file and no config array. What sits under the heading are two warnings about PHP versions that do not exist yet from the library's point of view, plus one note about a Composer warning. The first warning says that starting with PHP 8.6, deprecation notices will be triggered if you use the package with SplFileObject or SplTempFileObject instances, and it links the PHP wiki entry for deprecating the SplFileObject CSV methods. The second says that starting with PHP 8.4, deprecation notices will be triggered if you do not explicitly set the escape parameter, and it links both the deprecations entry for the proprietary CSV escaping mechanism and a separate write-up on CSV and PHP 8.4.

Both are about the language moving underneath a library that leans on PHP's own CSV handling, which is consistent with the stated goal of using native features whenever possible. The cost of that goal is stated plainly: on PHP 8.4 the caller has to pass the escape parameter on purpose rather than inherit a default that is being withdrawn. Neither warning says which value to pass, only that it must be set.

The two are dated by PHP release, not by library release, so they apply to every 9.x the reader might have pinned.

The package ships its own SortDirection polyfill, which is why Composer warns

The third callout is longer and explains an odd warning. Starting with version 9.29, an application that also uses symfony/polyfill-php86 may see Composer report an ambiguous class resolution warning for SortDirection. The page says this is expected and harmless, and gives the reason: both packages include the same SortDirection polyfill, and that is deliberate so league/csv can also be used without Composer.

The rest of the note explains how the two copies stay quiet. On PHP 8.6 and later, SortDirection is provided by PHP itself, and the polyfill does not declare the enum. On older PHP versions, the polyfill provides the enum when it is not already available. So the collision only exists on the versions where neither PHP nor one of the two packages is supposed to be the source, and the note closes by saying no action is required when the warning is reported.

A `polyfill/` directory sits at the root of the tree, which is where that shipping copy lives. It is not mentioned in the highlights or anywhere else on the page.

The one setting with code attached is for legacy Macintosh line endings

Four callouts, and only one of them contains anything to paste:

php
if (!ini_get('auto_detect_line_endings')) {
    ini_set('auto_detect_line_endings', '1');
}

The condition it is guarding against is a document created or read on a legacy Macintosh computer, whose line endings PHP will not otherwise recognise. The snippet is written as a guard rather than a set, so it leaves an operator's existing setting alone, and it goes before the library is used. The link attached to it points at the return values section of PHP's own fgetcsv documentation, which is where the setting is actually described.

So the entire configuration surface of this library, as the page presents it, is one ini flag for one legacy line ending, plus two warnings about future PHP releases, plus one note about a Composer message. There is no configuration file in the tree and no documented option list. The tree does hold an `autoload.php` at the root and a `polyfill/` directory, neither of which the page describes.

Three test suites, and two root tools the page never names

The testing section lists three suites rather than one: a PHPUnit test suite, a coding style compliance suite using PHP CS Fixer, and a code analysis compliance suite using PHPStan. All three are run with a single command from the project folder:

bash
composer test

The tree backs those up and goes further. `.php-cs-fixer.php` configures the style suite, `phpstan.neon` configures the analysis suite, and `phpunit.xml` configures the unit tests. Two more configuration files at the root are named nowhere on the page: `phpbench.json`, which configures a benchmark tool, and `rector.php`, which configures an automated refactoring tool. Neither appears in the highlights, the testing section, or the contributing notes, so a reader has no way to learn from the front page that either is part of the project.

There is also a `test_files/` directory at the root, which is where fixture documents for those tests would live, and a `docs/` directory, which is the source of the documentation the page links at csv.thephpleague.com. The highlights say the library is fully unit tested, which understates what the testing section actually runs.

Security reports go to one inbox, and the same handle is on the credits list

The security section is two sentences and one address. If you discover any security related issue, the instruction is to email a named individual rather than use the issue tracker. That is a deliberate choice, and a common one, but it means security triage depends on one person rather than on a queue. The credits list names that same person, with a link to a profile, followed by a link to the contributors graph, so the repository has one named maintainer and everyone else behind an aggregate link.

The rest of the page closes out conventionally: contributions are welcomed and will be fully credited, with links to a contributing guide and a code of conduct under `.github/`; the changelog lives in `CHANGELOG.md` at the root; and the license is MIT with a pointer to the `LICENSE` file.

The prose has a few small slips worth noting because they recur. The library is written as `Csv` in the requirements text while the package is `league/csv`, the goal sentence reads the library goal is to be powerful where it reads the goal of the library, and the highlight about format conversion says into popular format rather than into a popular format. None of that affects behaviour, and all of it is the kind of thing a maintainer would fix in one pass.

Editorial conclusion

Adequate fit: a PHP project that has to read or write CSV larger than memory, wants array to object mapping and format conversion without pulling in a framework, and can pin a minor version. It fits badly for a codebase still on PHP 7, because the compatibility table shows the minimum PHP climbing from 7.0.10 in the oldest rows to 8.2.0 in the newest, and the install constraint permits any 9.x. Four things are worth checking first. `composer require league/csv:^9.0` resolves to whichever 9.x is newest, so it can land on a release requiring a newer PHP than the table's first rows allowed. The table's own last row names 9.29.0, ahead of the 9.28.0 release. From PHP 8.4 the escape parameter has to be set explicitly or deprecation notices fire, and from PHP 8.6 the SplFileObject and SplTempFileObject CSV methods are on the same path. And the package ships its own SortDirection polyfill, so a project that also pulls symfony/polyfill-php86 will see a Composer warning that the page says is expected and harmless. Nothing above was installed or run.

Frequently asked questions

How can I read a CSV file in PHP?

Install this library with `composer require league/csv:^9.0` and read through its streaming reader, which the page describes as memory efficient and scalable instead of loading the whole document. You need the ext-filter extension, and from PHP 8.4 you must set the escape parameter explicitly or deprecation notices are triggered.

How can I create a CSV file using PHP?

This library is for parsing, writing and filtering CSV in PHP, and it installs with the same single composer command. It also transforms a CSV document into JSON, XML or HTML, and it supports PHP stream filtering capabilities.

Which PHP versions does League CSV support?

The table for version 9 has eleven rows. The minimum PHP rises from 7.0.10 in the earliest rows to 8.2.0 in the newest, the four oldest rows cap at PHP 7.x and 8.0.x, and the two newest say PHP 8.x with no upper bound. The last row names library version 9.29.0.

What does League CSV need besides PHP itself?

The ext-filter extension, which the requirements section names, plus the latest stable PHP is recommended. No other extension is listed in that section.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. thephpleague/csv on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/thephpleague-csv.svg)](https://hysenlabs.com/projects/thephpleague-csv)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/thephpleague-csv.svg)](https://hysenlabs.com/projects/thephpleague-csv)

Was this useful?