diff --git a/CHANGELOG.md b/CHANGELOG.md index 912d730f..1eb3402c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,8 +23,8 @@ All Notable changes to `Csv` will be documented in this file ### Removed -- polyfill for `is_iterable` -- polyfill for `is_nullable_int` +- Internal polyfill for `is_iterable` +- Internal polyfill for `is_nullable_int` - Support for PHP7.0 and PHP7.1 ## 9.5.0 - 2019-12-15 diff --git a/composer.json b/composer.json index d4e8281f..da24ed7b 100644 --- a/composer.json +++ b/composer.json @@ -19,6 +19,12 @@ "rss": "https://github.com/thephpleague/csv/releases.atom", "source": "https://github.com/thephpleague/csv" }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nyamsprod" + } + ], "require": { "php" : "^7.2.5", "ext-json" : "*", diff --git a/docs/9.0/reader/index.md b/docs/9.0/reader/index.md index 664209c4..a56ba62f 100644 --- a/docs/9.0/reader/index.md +++ b/docs/9.0/reader/index.md @@ -11,6 +11,8 @@ The `League\Csv\Reader` class extends the general connections [capabilities](/9.

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.

+

Starting with version 9.6.0, the class implements the League\Csv\TabularDataReader interface.

+ ## CSV example Many examples in this reference require an CSV file. We will use the following file `file.csv` containing the following data: diff --git a/docs/9.0/reader/resultset.md b/docs/9.0/reader/resultset.md index 4db9e6d7..143eea85 100644 --- a/docs/9.0/reader/resultset.md +++ b/docs/9.0/reader/resultset.md @@ -7,6 +7,8 @@ title: Accessing Records from a CSV document A `League\Csv\ResultSet` object represents the associated result set of processing a [CSV document](/9.0/reader/) with a [constraint builder](/9.0/reader/statement/). This object is returned from [Statement::process](/9.0/reader/statement/#apply-the-constraints-to-a-csv-document) execution. +

Starting with version 9.6.0, the class implements the League\Csv\TabularDataReader interface.

+ ## Informations ### Accessing the result set column names @@ -25,7 +27,7 @@ use League\Csv\Reader; use League\Csv\Statement; $reader = Reader::createFromPath('/path/to/my/file.csv', 'r'); -$records = (new Statement())->process($reader); +$records = Statement::create()->process($reader); $records->getHeader(); // is empty because no header information was given ~~~ @@ -37,7 +39,7 @@ use League\Csv\Reader; $reader = Reader::createFromPath('/path/to/my/file.csv', 'r'); $reader->setHeaderOffset(0); -$records = (new Statement())->process($reader); +$records = Statement::create()->process($reader); $records->getHeader(); // returns ['First Name', 'Last Name', 'E-mail']; ~~~ @@ -50,7 +52,7 @@ use League\Csv\Statement; $reader = Reader::createFromPath('/path/to/my/file.csv', 'r'); $reader->setHeaderOffset(0); -$records = (new Statement())->process($reader, ['Prénom', 'Nom', 'E-mail']); +$records = Statement::create()->process($reader, ['Prénom', 'Nom', 'E-mail']); $records->getHeader(); // returns ['Prénom', 'Nom', 'E-mail']; ~~~ @@ -63,7 +65,7 @@ use League\Csv\Reader; use League\Csv\Statement; $reader = Reader::createFromPath('/path/to/my/file.csv', 'r'); -$records = (new Statement())->process($reader); +$records = Statement::create()->process($reader); count($records); //return the total number of records found ~~~ @@ -72,8 +74,9 @@ count($records); //return the total number of records found ### Description ~~~php -public ResultSet::getRecords(void): Iterator +public ResultSet::getRecords(array $header = []): Iterator ~~~ +

Starting with version 9.6.0, the class implements the ResultSet::getRecords methods matches the same arguments and the same signature as the Reader::getRecords method.

To iterate over each found records you can call the `ResultSet::getRecords` method which returns a `Generator` of all records found or directly use the `foreach` construct as the class implements the `IteratorAggregate` interface; @@ -82,7 +85,7 @@ use League\Csv\Reader; use League\Csv\Statement; $reader = Reader::createFromPath('/path/to/my/file.csv', 'r'); -$records = (new Statement())->process($reader); +$records = Statement::create()->process($reader); foreach ($records->getRecords() as $record) { //do something here @@ -103,7 +106,7 @@ use League\Csv\Statement; $reader = Reader::createFromPath('/path/to/my/file.csv', 'r'); $reader->setHeaderOffset(0); -$records = (new Statement())->process($reader); +$records = Statement::create()->process($reader); $records->getHeader(); //returns ['First Name', 'Last Name', 'E-mail'] foreach ($records as $record) { // $records contains the following data @@ -133,7 +136,7 @@ use League\Csv\Statement; $reader = Reader::createFromPath('/path/to/my/file.csv', 'r'); $reader->setHeaderOffset(0); -$stmt = (new Statement()) +$stmt = Statement::create() ->offset(10) ->limit(12) ; @@ -163,7 +166,7 @@ use League\Csv\Reader; use League\Csv\Statement; $reader = Reader::createFromPath('/path/to/my/file.csv', 'r'); -$records = (new Statement())->process($reader); +$records = Statement::create()->process($reader); foreach ($records->fetchColumn(2) as $value) { //$value is a string representing the value //of a given record for the selected column @@ -173,7 +176,7 @@ foreach ($records->fetchColumn(2) as $value) { $reader = Reader::createFromPath('/path/to/my/file.csv', 'r'); $reader->setHeaderOffset(0); -$records = (new Statement())->process($reader); +$records = Statement::create()->process($reader); foreach ($records->fetchColumn('E-mail') as $value) { //$value is a string representing the value //of a given record for the selected column @@ -188,7 +191,7 @@ use League\Csv\Reader; use League\Csv\Statement; $reader = Reader::createFromPath('/path/to/my/file.csv', 'r'); -$records = (new Statement())->process($reader); +$records = Statement::create()->process($reader); count($records); //returns 10; count(iterator_to_array($records->fetchColumn(2), false)); //returns 5 //5 records were skipped because the column value is null @@ -203,7 +206,7 @@ use League\Csv\Statement; $reader = Reader::createFromPath('/path/to/my/file.csv', 'r'); $reader->setHeaderOffset(0); -$records = (new Statement())->process($reader); +$records = Statement::create()->process($reader); foreach ($records->fetchColumn('foobar') as $record) { //throw an Exception exception if //no `foobar` column name is found @@ -240,7 +243,7 @@ use League\Csv\Reader; use League\Csv\Statement; $reader = Reader::createFromString($str); -$records = (new Statement())->process($reader); +$records = Statement::create()->process($reader); foreach ($records->fetchPairs() as $firstname => $lastname) { // - first iteration @@ -289,7 +292,7 @@ foreach ($records as $record) { } $reader = Reader::createFromFileObject($tmp)->setHeaderOffset(0); -$stmt = (new Statement())->offset(1)->limit(1); +$stmt = Statement::create()->offset(1)->limit(1); $result = $stmt->process($reader); echo '
', PHP_EOL;
diff --git a/docs/9.0/reader/statement.md b/docs/9.0/reader/statement.md
index a491dcb8..5a7ecab0 100644
--- a/docs/9.0/reader/statement.md
+++ b/docs/9.0/reader/statement.md
@@ -11,6 +11,8 @@ When building a constraint, the methods do not need to be called in any particul
 
 

Because the Statement object is independent of the Reader object it can be re-use on multiple Reader objects.

+

Starting with version 9.6.0, the class exposes the Statement::create named constructor to ease object creation.

+ ## Filtering constraint The filters attached using the `Statement::where` method **are the first settings applied to the CSV before anything else**. This option follow the *First In First Out* rule. @@ -109,23 +111,33 @@ Just like the `Reader:getRecords`, the `Statement::process` method takes an opti use League\Csv\Reader; use League\Csv\Statement; -function filterByEmail(array $record): bool -{ - return (bool) filter_var($record[2], FILTER_VALIDATE_EMAIL); -} - -function sortByLastName(array $recordA, array $recordB): int -{ - return strcmp($recordB[1], $recordA[1]); -} - $reader = Reader::createFromPath('/path/to/file.csv', 'r'); -$stmt = (new Statement()) +$stmt = Statement::create() ->offset(3) ->limit(2) - ->where('filterByEmail') - ->orderBy('sortByLastName') + ->where(fn(array $record) => (bool) filter_var($record[2], FILTER_VALIDATE_EMAIL)) + ->orderBy(fn(array $recordA, array $recordB) => strcmp($recordB[1], $recordA[1])) ; $records = $stmt->process($reader, ['firstname', 'lastname', 'email']); ~~~ + +

Starting with version 9.6.0, the Statement::process method can also be used on the ResultSet class because it implements the TabularDataReader interface.

+ +~~~php +use League\Csv\Reader; +use League\Csv\Statement; + +$reader = Reader::createFromPath('/path/to/file.csv', 'r'); +$stmt = Statement::create() + ->where(fn(array $record) => (bool) filter_var($record[2], FILTER_VALIDATE_EMAIL)) + ->orderBy(fn(array $recordA, array $recordB) => strcmp($recordB[1], $recordA[1])) +; + +$resultSet = $stmt->process($reader, ['firstname', 'lastname', 'email']); + +$stmt2 = Statement::create(null, 3, 2); +$records = $stmt2->process($resultSet); +// the $records and the $resultSet parameters are distinct League\Csv\ResultSet instances. +~~~ +