League\Csv 7 is out

Attention: Les informations de ce billet sont susceptibles d'être obsolètes car vieux de plus 2 ans.

Warning: The information you are reading may be obsolete, this post was published more than 2 years ago.

League\Csv 7  has been officially released! The new version is as simple and as powerful as before but adds more speed and flexibility to the package. Features introduced during the version 6.0 series are now stabilized and care was taken to improved the package manipulation of huge CSV files.

Installing League\Csv 7 using composer is as simple as typing the code below in your composer installed box.

$ composer require league\csv

This should install/update your composer powered project to the latest stable version of the library.

What is League\Csv ?

For those non familiar with the library, it’s a set of two classes League\Csv\Reader and League\Csv\Writer that make it painless to interact with CSV documents if your are using a supported version of PHP. Let’s say you have some CSV data that you want to import into your database. League\Csv\Reader will help you do that as simple as possible with the following code:

<?php
use League\Csv\Reader;

//We are going to insert some data into the users table
$sth = $dbh->prepare(
     "INSERT INTO users (firstname, lastname, email) VALUES (:firstname, :lastname, :email)"
);

$csv = Reader::createFromPath('/path/to/your/csv/file.csv');
$csv->setOffset(1); //because we don't want to insert the header
$nbInsert = $csv->each(function ($row) use (&$sth) {
    //Do not forget to validate your data before inserting it in your database
    $sth->bindValue(':firstname', $row[0], PDO::PARAM_STR);
    $sth->bindValue(':lastname', $row[1], PDO::PARAM_STR);
    $sth->bindValue(':email', $row[2], PDO::PARAM_STR);

    return $sth->execute(); //if the function return false then the iteration will stop
});
echo $nbInsert; //display the number of successfull inserts done

More examples and usage can be found in the examples directory attached to the library on the github repository.

What’s changed ?

Mac OS X users will now be required to update their PHP ini setting to allow the library to work as intended on their environment.

Since version 5.3 the auto_detecting_line_ending PHP ini setting was activated by default by the library. The problem is that the library was messing with the developer environment without informing him which could lead to unexpected side effects without warning. By removing this setting, the developer gains back the full control over his environment.

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

//the rest of the code continue here...

The Writer class has been rewritten to be faster and more flexible.

Previous version of the League\Csv\Writer class performed, out of the box, a number of validation and formatting that were slowing down row insertions. To solve this issue while still being able to control/manipulate the inserted data version 7.0 introduce a new flexible mechanism illustrate below

<?php

use League\Csv\Writer;
use League\Csv\Exception\InvalidRowException;

try {
    $formatter = function (array $row) {
        return array_map('strtoupper', $row);   
    };
    $validator = function (array $row) {
        return 10 == count($row);
    };
    $writer = Writer::createFromPath('/path/to/my/file.csv');
    $writer->addFormatter($formatter);
    $writer->addValidator($validator, 'row_must_contain_10_cells');
    //$rows is a multidimentional array or a Traversable object
    $writer->insertAll($rows);  
} catch (InvalidRowException $e) {
    $e->getName(); //the name of the validator where the row failed 'row_must_contain_10_cells'
    $e->getData(); //the data which failed the validator for instance ["foo", "bar", "baz"]
}

You can of course attach as many filters as you want. But keep in mind that more filters means slower data insertion.

This is a major departure from previous versions and the migration guide will provide all the information needed to migrate your code if necessary.

You can no longer use classes default constructor to instantiated them. You are required to use one of the 3 named constructors.

Using named constructors is the recommended way to instantiate the Writer and the Reader objects since version 6. We are now taking the next logical step to remove remaining ambiguities when creating a League\Csv object by  removing the default constructor from public API.

Conversion methods output can now be modified using the League\Csv\Reader query options

Conversion methods that transform your CSV into JSON, XML or HTML were introduced in the package prior to the League\Csv\Reader query options. As such they were restricted to work on the full CSV document only. Starting with version 7.0, a backward compatibility break is introduced to enable these methods to be more flexible when used with the Reader.

<?php

use League\Csv\Reader;

$reader = Reader::createFromPath('/path/to/your/csv/file.csv');
$reader->setOffset(1);
$reader->setLimit(5);
json_encode($reader); //will only convert the 5 specified rows and not the full CSV like previously

Do keep in mind though, that the same restrictions to the use of query options still remain.

The detectDelimiterList method now returns the delimiter and its occurrence in the selected rows.

This method introduced in the last version returned an array containing the founded delimiters ordered by their occurrences but the occurrence information was not given. With this backward compatibility break the information is now available to the developer.

use League\Csv\Reader;

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

$delimiters_list = $reader->detectDelimiterList(10, [' ', '|']);
if (count($delimiters_list)) {
	foreach ($delimiters_list as $occurences => $delimiter) {
		echo "$delimiter appeared $occurences times in 10 CSV row", PHP_EOL;
	}
	//$occurences can not be less than 1
	//since it would mean that the delimiter is not used
}
//if you are only interested in getting
// the most use delimiter you can still do as follow
if (count($delimiters_list)) {
	$delimiter = array_shift($delimiters);
}

Upgrading to League\Csv 7

Even thought this package introduces many backward compatibility breaks. I’m confident that upgrading to League\Csv 7 won’t require changes for most users. For a full list of the changes please refer to the CHANGELOG.md file attached to the library and see the upgrading guide for more information.

Last but not least

The League\Csv is an open source project with a MIT License so contributions are more than welcome and will be fully credited.  These contributions can be anything from reporting an issue, requesting or adding missing features or simply improving or correcting some typo on the documentation website.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.