Re: [RFC] CSV Extension (ext/csv)

From: Date: Sun, 11 Oct 2026 11:50:25 +0000
Subject: Re: [RFC] CSV Extension (ext/csv)
References: 1 2  Groups: php.internals 
Request: Send a blank email to internals+get-132863@lists.php.net to get a copy of this message
Hi everyone, Thank you for the feedback, and Artem, for the detailed review and independent verification of the implementation. I think the discussion has raised two important questions: whether these improvements belong in the existing CSV API or a dedicated extension, and what an API supporting both files and already-open streams should look like.. Artem, your point about incremental improvements is fair. The RFC's statement that the existing behaviour “cannot be fixed without breaking compatibility” is too broad. Several improvements could be introduced through additional functions or opt-in behaviour while preserving existing calls. You are also right that enclosing fields containing spaces is permitted by RFC 4180, and that locale-independent byte parsing has different implications for encodings such as Shift_JIS. At the same time, PHP has taken the approach of introducing a modern API alongside an established one when their contracts differ substantially. The new DOM API, including Dom\Document, coexists with the legacy DOMDocument API, and the URI extension provides a dedicated API alongside parse_url(). These are relevant precedents for giving users clearer semantics without changing the behaviour of existing applications. Of course, those precedents do not automatically justify another CSV parser. They do suggest that improving the existing API and introducing a dedicated one are both reasonable approaches to evaluate. The question is whether the consistency and usability of the proposed CSV API justify its maintenance cost. My motivation is to provide parsing, serialization, validation and file handling with consistent, explicit defaults. In particular, the file-based entry points accept a path and manage the underlying stream, covering the convenience previously provided by SplFileObject's CSV methods. The existing fgetcsv()/fputcsv() functions operate on streams supplied by the caller. Both use cases deserve support. Separately, the remaining overlapping-token writer issue reported on the PR has been addressed in https://github.com/php/php-src/commit/b7866156dc7e77304fe3419edceba6f890b113cb. Fields are now enclosed when tokens could form across field/separator boundaries. Distinguishable overlapping dialects remain supported; ambiguous combinations such as delimiter xy with enclosure xyx are rejected by both readers and writers. Regression tests cover both behaviours, and all 92 PHPT tests pass in my local verification. With those concerns in mind, I would like to discuss three possible directions: A. Improve the existing API in ext/standard, adding capabilities such as string serialization, multibyte tokens and opt-in strict parsing, with file and lazy-reading conveniences considered where needed. B. Continue with the dedicated ext/csv proposal, retaining its function-based API and lazy collection, while adding entry points for existing streams and resolving the naming questions. C. Rework the proposal around an object-oriented API in the Csv namespace, with explicit file and stream factories and writing methods. Stream ownership, iteration, validation and string conversion would need to be specified before this became a concrete voting option. My preference remains a dedicated API with consistent semantics, but I am open to revising its shape or pursuing the existing-API route if that is the direction the project prefers. Would a directional vote between these approaches be useful if discussion does not establish a clear preference? I would first document the alternatives and their trade-offs, and agree on the voting format. Selecting a direction would guide a revised proposal; it would not approve an API whose details have yet to be reviewed. The current RFC does not propose deprecating the existing CSV functions. Any future consolidation would need its own discussion and an established migration path, rather than assuming that introducing a new API commits PHP to removing the old one. The goal is to establish a maintainable CSV path for PHP users, including those migrating from the deprecated SplFileObject methods. I would welcome your thoughts on which direction best serves that goal. Best regards, Damian On Sat, Oct 10, 2026 at 12:38 PM Artem Ukrainskiy <art.ukrainskiy@gmail.com> wrote: > This RFC led me to take a closer look at the built-in CSV functions, and > what I found makes me favor a different path to the same goals. > > The RFC argues that their behavior "cannot be fixed without breaking > compatibility". I went through the list: > > - $escape: already addressed by the PHP 8.4 deprecation; the default > changes to "" in PHP 9.0. > > - Locale dependence: php/php-src#24207 ( > https://github.com/php/php-src/pull/24207, under review, > prompted by this > RFC) removes the per-byte libc lookup for ASCII characters in > ASCII-compatible locales. The remaining isspace() before an opening > enclosure can be replaced with an explicit space/tab check. For non-ASCII > bytes in CJK locales, mbrlen() serves a purpose: a Shift_JIS character can > contain a '|' trail byte without that byte being a delimiter. A > locale-independent byte parser would split it. > > - Single-byte delimiters and enclosures: longer values currently throw > ValueError, so support for multibyte tokens can be added without changing > existing valid calls. > > - No inverse of str_getcsv(): a str_putcsv() function would fill that gap > and let SplFileObject::fputcsv() callers use > $file->fwrite(str_putcsv($row)). > > - [null] for an empty line and whitespace before an enclosure: these can > be addressed by an opt-in strict mode without changing the default > behavior. Enclosing fields containing spaces on output is permitted by RFC > 4180 section 2.5 and is not a compliance defect. > > Strict validation, multibyte tokens, string serialization and lazy reading > can all be built on the existing API. Lazy iteration over a stream already > works with a generator around fgetcsv(); strict row-width validation can be > layered on top. These changes can be developed and reviewed independently, > without replacing the parser or breaking existing calls. > > I have benchmarks and test scripts for the existing implementation and the > proposed extension here: > > https://github.com/ArtUkrainskiy/php-src-bench/tree/main/reports/csv-pr-24199_ǝwüÿc~X > ¾g > > Adding ext/csv instead would leave core maintaining two independent CSV > parsers for the foreseeable future. The RFC explicitly leaves the built-ins > unchanged, and the June discussion around the SplFileObject deprecations > showed understandable reluctance to remove existing APIs without an > established migration path (https://news-web.php.net/php.internals/131503, > and the August follow-up: > https://news-web.php.net/php.internals/132186). > > The branch itself is in good shape. The issues I reported on the PR were > addressed quickly, and the parser is now faster than fgetcsv() in my > benchmarks. This is not an objection to the implementation or the work that > went into it. > > My concern is the long-term maintenance cost of introducing a second > parser when the existing one can be improved incrementally. I'd rather help > land those improvements in ext/standard. > > пт, 9 окт. 2026 г. в 17:07, Damian Jóźwiak <damian.jozwiak.lodz@gmail.com > >: > >> >> Hi internals, >> >> I'd like to open the discussion on an RFC proposing a dedicated CSV >> extension (ext/csv) for PHP core. >> >> RFC: https://wiki.php.net/rfc/csv_extension >> >> Implementation: https://github.com/php/php-src/pull/24199 >> >> The proposal builds upon Gina Peter Banyard's girgias/csv extension >> (BSD-3-Clause), with additional functionality for file and stream handling. >> >> The motivation includes the deprecation of the SplFileObject CSV methods >> in PHP 8.6, which leaves certain use cases without a direct replacement. >> >> The proposed extension provides: >> >> - >> >> Six functions and one class in the Csv\ namespace. >> - >> >> RFC 4180-compatible parsing and serialization by default. >> - >> >> Locale-independent processing without the proprietary escape >> mechanism. >> - >> >> Multibyte delimiters, enclosures, and EOL sequences. >> - >> >> Strict and lax collection parsing. >> - >> >> Lazy iteration over CSV files and streaming output. >> >> The implementation includes PHPT tests covering parsing, serialization, >> stream handling, resource lifetime, and various edge cases. >> >> The pull request's CI checks are currently passing across the tested >> platforms, including debug, ZTS, and AddressSanitizer configurations. >> >> The initial API is deliberately kept small. A more comprehensive >> object-oriented Reader/Writer API, including capability-oriented >> interfaces, is left for potential future discussion. >> >> I'd particularly appreciate feedback on the public API design, the naming >> of LazyLaxCollection, and whether the extension should be always enabled >> or optional at build time. >> >> For transparency, Gina has not reviewed or endorsed this RFC. Parts of >> the implementation were developed with LLM assistance; I have reviewed the >> code and take full responsibility for the contribution. >> >> This is an invitation for discussion, not a call for votes. >> >> Thanks in advance for your feedback. >> >> Best regards, >> Damian Jóźwiak >> > > > -- > Best regards, > Artem Ukrainskiy > >

« previous php.internals (#132863) next »