thephpleague/csv

repository·master·Indexed 25 days ago

https://github.com/thephpleague/csv

A lightweight and memory-efficient PHP library for parsing, writing, and filtering CSV documents. It provides tools for iterating over CSV rows via League\Csv\Reader, exporting data using League\Csv\Writer, and converting CSV data to XML or HTML. The library supports BOM detection and configuration for MS Excel compatibility on Windows and MacOS, as well as stream filtering for encoding transcoding.

Tokens
69.9K
Snippets
230
Records
349
Agent score
84%

What's inside league/csv

  1. Understand the TabularDataReader interface

    master

    The League\Csv\TabularDataReader interface (introduced in version 9.6) provides a common API for handling tabular data structures, such as CSV documents, HTML tables, or RDBMS tables.

    A tabular data structure consists of:

    • A collection of similar, non-nested PHP array records.
    • An optional header containing unique string values.

    TabularDataReader implementations (like Reader) are generally immutable; methods like filter(), select(), and slice() return a new instance, leaving the original data unchanged.

  2. Choose between Reader and Writer for CSV access

    master

    Access CSV documents using one of two primary classes depending on your required mode:

    • League\Csv\Reader: Use this for read-only mode.
    • League\Csv\Writer: Use this for write-only mode.

    Both classes extend League\Csv\AbstractCsv and share features for loading documents, setting control characters, managing BOM sequences, adding PHP stream filters, and outputting documents.

  3. Check system requirements for CSV

    master

    To use the Csv library, ensure your environment meets the following requirements:

    • The ext-filter PHP extension must be installed.
    • PHP version compatibility depends on the library version. For version 9.16.0 and above, PHP 8.1.2 or higher is required (supports up to PHP 8.x).
  4. Use the Tabular Data Buffer for CRUD operations

    master

    The League\Csv\Buffer class (available since version 9.22.0) allows you to manage and transform tabular data using basic CRUD operations.

    Warning: The Buffer stores all data in-memory. It does not use PHP streams like Reader or Writer, so it cannot handle extremely large datasets. You must manually limit the size of the data loaded into it to avoid memory exhaustion.

  5. Handle multibyte delimiters using SwapDelimiter

    master

    The League\Csv\SwapDelimiter stream filter allows you to process CSV documents that use multibyte characters (like emojis or specific symbols) as delimiters.

    Important Requirements:

    1. Single-byte Delimiter: You must first set the CSV object's delimiter to a single-byte character (e.g., \x02) before calling SwapDelimiter::addTo. This single-byte character should ideally be an ASCII character between 1 and 32 (excluding line endings) that does not appear in your data.
    2. Order of Operations: Always set the single-byte delimiter before calling SwapDelimiter::addTo.
    3. Behavior:
      • For a Writer, it converts the single-byte delimiter into your specified multibyte $sourceDelimiter during output.
      • For a Reader, it converts the multibyte $sourceDelimiter into the single-byte delimiter during input.
    4. Data Integrity: When reading, the original CSV content is never changed or replaced; the conversion happens during the stream processing.
    use League\Csv\SwapDelimiter;
    use League\Csv\Writer;
    
    $writer = Writer::fromString();
    $writer->setDelimiter("\x02");
    SwapDelimiter::addTo($writer, '💩');
    $writer->insertOne(['toto', 'tata', 'foobar']);
    $writer->toString();
    // returns toto💩tata💩foobar\n
  6. Read CSV documents using Reader

    master

    Use the Reader class to access CSV records. You can load a CSV from a file path or a stream. Once loaded, you can set a header offset to treat a specific row as the header.

    Key methods:

    • setHeaderOffset(int $offset): Sets the row index to be used as the header.
    • getHeader(): Returns the header record.
    • getRecords(): Returns an Iterator containing records as arrays.
    • getRecordsAsObject(string $className): Returns an Iterator containing records mapped to a specific DTO class.
    • toString(): Returns the entire CSV document as a string.
    use League\Csv\Reader;
    
    //load the CSV document from a file path
    $csv = Reader::from('/path/to/your/csv/file.csv', 'r');
    $csv->setHeaderOffset(0);
    
    $header = $csv->getHeader(); //returns the CSV header record
    
    //returns all the records as
    $records = $csv->getRecords(); // an Iterator object containing arrays
    $records = $csv->getRecordsAsObject(MyDTO::class); //an Iterator object containing MyDTO objects
    
    echo $csv->toString(); //returns the CSV document as a string
  7. Handle null values in Writer (v7.x)

    master

    In version 7.x, setNullHandlingMode has been removed from the Writer class. By default, null values are converted to empty strings. To replicate previous behaviors, use the following plugins:

    1. To throw an exception on nulls: Use League\Csv\Plugin\ForbiddenNullValuesValidator.
    2. To skip null cells: Use League\Csv\Plugin\SkipNullValuesFormatter.
    use League\
    Csv\\Writer;
    use League\Csv\Plugin\ForbiddenNullValuesValidator;
    
    $validator = new ForbiddenNullValuesValidator();
    $writer = Writer::createFromPath('/path/to/your/csv/file.csv');
    $writer->addValidator($validator, 'null_as_exception');
    $writer->insertOne(['foo', null, 'bar']); // throws League\Csv\Exception\InvalidRowException
  8. Use the Statement class to query CSV data

    master
    The League\Csv\Statement class acts as a constraint builder (similar to a database query builder) to filter, order, and limit CSV records. It is immutable; every method call returns a new Statement instance. Once constraints are defined, use the process() method on a TabularDataReader (like a Reader) to obtain a ResultSet.
  9. Manage stream filter lifecycle and removal

    master

    Stream filters attached via the League\Csv API (addStreamFilter, appendStreamFilterOn*, prependStreamFilterOn*) are automatically removed when the CSV object is destroyed.

    However, if you attach a filter directly to the underlying stream using PHP's native stream_filter_append or stream_filter_prepend before passing it to a Reader or Writer, the library will not detect it via hasStreamFilter(), and it will not be removed when the CSV object is destroyed.

    use League\Csv\Reader;
    
    $fp = fopen('/path/to/my/chines.csv', 'r');
    // Attached outside of League\Csv
    stream_filter_append($fp, 'string.rot13'); 
    
    $reader = Reader::from($fp);
    $reader->prependStreamFilterOnRead('convert.utf8decode');
    
    // This returns false because it was added via native PHP, not the library API
    $reader->hasStreamFilter('string.rot13'); // returns false
    
    $reader = null;
    // 'string.rot13' is still attached to the file pointer $fp
  10. Handle character encoding with PHP Stream filters

    master

    You can use the Bom class to detect Byte Order Marks (BOM) and apply PHP stream filters to the Reader to handle character encoding conversions (e.g., UTF-16 to UTF-8) during iteration.

    use League\Csv\Reader;
    use League\Csv\Bom;
    
    $csv = Reader::from('/path/to/your/csv/file.csv', 'r');
    $csv->setHeaderOffset(0);
    
    if (Bom::tryFromSequence($csv)?->isUtf16() ?? false) {
        $csv->appendStreamFilterOnRead('convert.iconv.UTF-16/UTF-8');
    }
    
    foreach ($csv as $record) {
        //all fields from the record are converted from UTF-16 into UTF-8 charset
        //and the BOM sequence is removed
    }
  11. Parse a CSV document from the local filesystem

    master

    Use League\Csv\Reader to load a CSV file and League\Csv\Statement to apply filters like offsets and limits.

    Note for PHP 8.4+ users: You must call $csv->setEscape('') to avoid deprecation notices.

    use League\Csv\Reader;
    use League\Csv\Statement;
    
    $csv = Reader::from('/path/to/your/csv/file.csv', 'r');
    $csv->setHeaderOffset(0); //set the CSV header offset
    $csv->setEscape(''); //required in PHP8.4+ to avoid deprecation notices
    
    //get 25 records starting from the 11th row
    $stmt = new Statement()
        ->offset(10)
        ->limit(25)
    ;
    
    $records = $stmt->process($csv);
    foreach ($records as $record) {
        //do something here
    }
  12. Validate row consistency in Writer (v7.x)

    master

    Direct row consistency checking was removed from the Writer class in version 7.x. Use the League\Csv\Plugin\ColumnConsistencyValidator to manage column counts and consistency.

    use League\Csv\Writer;
    use League\Csv\Plugin\ColumnConsistencyValidator;
    
    $validator = new ColumnConsistencyValidator();
    $validator->autodetectColumnsCount();
    $validator->getColumnsCount(); // returns -1
    
    $writer = Writer::createFromPath('/path/to/your/csv/file.csv');
    $writer->addValidator($validator, 'column_consistency');
    
    $writer->insertOne(['foo', null, 'bar']);
    $nb_column_count = $validator->getColumnsCount(); // returns 3