The League of Extraordinary Packages

Our Packages:

Presented by The League of Extraordinary Packages

Getting Started

Connections Settings

Inserting Records

Selecting Records

Interoperability

Converting Records

Upgrading Guide

Reader Connection

<?php

class Reader extends AbstractCsv implements Countable, IteratorAggregate, JsonSerializable
{
    public function fetchColumn(string|int $columnIndex = 0): Generator
    public function fetchOne(int $nth_record = 0): array
    public function fetchPairs(string|int $offsetIndex = 0, string|int $valueIndex = 1): Generator
    public function getHeader(): array
    public function getHeaderOffset(): ?int
    public function getRecords(array $header = []): Iterator
    public function setHeaderOffset(?int $offset): self
}

The League\Csv\Reader class extends the general connections capabilities to ease selecting and manipulating CSV document records.

Starting with version 9.1.0, createFromPath when used from the Reader object will have its default set to r.

Prior to 9.1.0, by default, the mode for a Reader::createFromPath is r+ which looks for write permissions on the file and throws an Exception if the file cannot be opened with the permission set. For sake of clarity, it is strongly suggested to set r mode on the file to ensure it can be opened.

CSV example

Many examples in this reference require an CSV file. We will use the following file file.csv containing the following data:

"First Name","Last Name",E-mail
john,doe,john.doe@example.com
jane,doe,jane.doe@example.com
john,john,john.john@example.com
jane,jane

CSV header

You can set and retrieve the header offset as well as its corresponding record.

Description

<?php

public Reader::setHeaderOffset(?int $offset): self
public Reader::getHeaderOffset(void): ?int
public Reader::getHeader(void): array

Example

<?php

use League\Csv\Reader;

$csv = Reader::createFromPath('/path/to/file.csv', 'r');
$csv->setHeaderOffset(0);
$header_offset = $csv->getHeaderOffset(); //returns 0
$header = $csv->getHeader(); //returns ['First Name', 'Last Name', 'E-mail']

If no header offset is set:

By default no header offset is set.

Because the header is lazy loaded, if you provide a positive offset for an invalid record a Exception exception will be triggered when trying to access the invalid record.

<?php

use League\Csv\Reader;

$csv = Reader::createFromPath('/path/to/file.csv', 'r');
$csv->setHeaderOffset(1000); //valid offset but the CSV does not contain 1000 records
$header_offset = $csv->getHeaderOffset(); //returns 1000
$header = $csv->getHeader(); //triggers a Exception exception

CSV records

<?php

public Reader::getRecords(array $header = []): Iterator

Reader::getRecords basic usage

The Reader class let’s you access all its records using the Reader::getRecords method. The method returns an Iterator containing all CSV document records. It will also:

<?php

use League\Csv\Reader;

$reader = Reader::createFromPath('/path/to/my/file.csv', 'r');
$records = $reader->getRecords();
foreach ($records as $offset => $record) {
    //$offset : represents the record offset
    //var_export($record) returns something like
    // array(
    //  'john',
    //  'doe',
    //  'john.doe@example.com'
    // );
    //
}

Reader::getRecords with Reader::setHeaderOffset

If you specify the CSV header offset using setHeaderOffset, the found record will be combined to each CSV record to return an associated array whose keys are composed of the header values.

<?php

use League\Csv\Reader;

$reader = Reader::createFromPath('/path/to/my/file.csv', 'r');
$reader->setHeaderOffset(0);
$records = $reader->getRecords();
foreach ($records as $offset => $record) {
    //$offset : represents the record offset
    //var_export($record) returns something like
    // array(
    //  'First Name' => 'jane',
    //  'Last Name' => 'doe',
    //  'E-mail' => 'jane.doe@example.com'
    // );
    //
}

Reader::getRecords with its optional argument

Conversely, you can submit your own header record using the optional $header argument of the getRecords method.

<?php

use League\Csv\Reader;

$reader = Reader::createFromPath('/path/to/my/file.csv', 'r');
$records = $reader->getRecords(['firstname', 'lastname', 'email']);
foreach ($records as $offset => $record) {
    //$offset : represents the record offset
    //var_export($record) returns something like
    // array(
    //  'firstame' => 'jane',
    //  'lastname' => 'doe',
    //  'email' => 'jane.doe@example.com'
    // );
}

The optional $header argument from the Reader::getRecords takes precedence over the header offset property but its corresponding record will still be removed from the returned Iterator.

<?php

use League\Csv\Reader;

$reader = Reader::createFromPath('/path/to/my/file.csv', 'r');
$reader->setHeaderOffset(0);
$records = $reader->getRecords(['firstname', 'lastname', 'email']);
foreach ($records as $offset => $record) {
    //$offset : represents the record offset
    //var_export($record) returns something like
    // array(
    //  'firstame' => 'jane',
    //  'lastname' => 'doe',
    //  'email' => 'jane.doe@example.com'
    // );
}
//the first record will still be skip!!

In both cases, if the header record contains non unique string values, a Exception exception is triggered.

Using the IteratorAggregate interface

Because the Reader class implements the IteratorAggregate interface you can directly iterate over each record using the foreach construct and an instantiated Reader object.
You will get the same results as if you had called Reader::getRecords without its optional argument.

<?php

use League\Csv\Reader;

$reader = Reader::createFromPath('/path/to/my/file.csv', 'r');
$reader->setHeaderOffset(0);
foreach ($reader as $offset => $record) {
    //$offset : represents the record offset
    //var_export($record) returns something like
    // array(
    //  'First Name' => 'john',
    //  'Last Name' => 'doe',
    //  'E-mail' => john.doe@example.com'
    // );
    //
}

Records normalization

The returned records are normalized using the following rules:

<?php

use League\Csv\Reader;

$reader = Reader::createFromPath('/path/to/my/file.csv', 'r');
$reader->setHeaderOffset(0);
$records = $reader->getRecords();
foreach ($records as $offset => $record) {
    //$offset : represents the record offset
    //var_export($record) returns something like
    // array(
    //  'First Name' => 'jane',
    //  'Last Name' => 'jane',
    //  'E-mail' => null
    // );
    //
}

Records count

You can retrieve the number of records contains in a CSV document using PHP’s count function because the Reader class implements the Countable interface.

<?php

use League\Csv\Reader;

$reader = Reader::createFromPath('/path/to/my/file.csv', 'r');
count($reader); //returns 4

If a header offset is specified, the number of records will not take into account the header record.

<?php

use League\Csv\Reader;

$reader = Reader::createFromPath('/path/to/my/file.csv', 'r');
$reader->setHeaderOffset(0);
count($reader); //returns 3

The Countable interface is implemented using PHP's iterator_count on the Reader::getRecords method.

Records selection

Simple Usage

<?php

public Reader::fetchColumn(string|int $columnIndex = 0): Generator
public Reader::fetchOne(int $nth_record = 0): array
public Reader::fetchPairs(string|int $offsetIndex = 0, string|int $valueIndex = 1): Generator

Using method overloading, you can directly access all retrieving methods attached to the ResultSet object.

Example

<?php

use League\Csv\Reader;

$reader = Reader::createFromPath('/path/to/my/file.csv', 'r');

$records = $reader->fetchColumn(2);
//$records is a Generator representing all the fields of the CSV 3rd column

Advanced Usage

If you require a more advance record selection, you should use a Statement object to process the Reader object. The found records are returned as a ResultSet object.

Example

<?php

use League\Csv\Reader;
use League\Csv\Statement;

$reader = Reader::createFromPath('/path/to/my/file.csv', 'r');
$stmt = (new Statement())
    ->offset(3)
    ->limit(5)
;

$records = $stmt->process($reader);
//$records is a League\Csv\ResultSet object

Records conversion

Json serialization

The Reader class implements the JsonSerializable interface. As such you can use the json_encode function directly on the instantiated object. The interface is implemented using PHP’s iterator_array on the Reader::getRecords method. As such, the returned JSON string data depends on the presence or absence of a header.

<?php

use League\Csv\Reader;

$records = [
    ['firstname', 'lastname', 'e-mail', 'phone'],
    ['john', 'doe', 'john.doe@example.com', '0123456789'],
];

$tmp = new SplTempFileObject();
foreach ($records as $record) {
    $tmp->fputcsv($record);
}

$reader = Reader::createFromFileObject($tmp);
echo '<pre>', PHP_EOL;
echo json_encode($reader, JSON_PRETTY_PRINT), PHP_EOL;
//display
//[
//    [
//        "firstname",
//        "lastname",
//        "e-mail",
//        "phone"
//    ],
//    [
//        "john",
//        "doe",
//        "john.doe@example.com",
//        "0123456789"
//    ]
//]

$reader->setHeaderOffset(0);
echo '<pre>', PHP_EOL;
echo json_encode($result, JSON_PRETTY_PRINT), PHP_EOL;
//display
//[
//    {
//        "firstname": "john",
//        "lastname": "doe",
//        "e-mail": "john.doe@example.com",
//        "phone": "0123456789"
//    }
//]

The record offset is not preserved on conversion

To convert your CSV to JSON you must be sure its content is UTF-8 encoded, using, for instance, the library CharsetConverter stream filter.

Other conversions

If you wish to convert your CSV document in XML or HTML please refer to the converters bundled with this library.