Skip to content

Commit

Permalink
Merge pull request #2 from nyamsprod/develop
Browse files Browse the repository at this point in the history
Adding the ReaderInterface
  • Loading branch information
nyamsprod committed Jan 10, 2014
2 parents 8b003d0 + c3182d8 commit b278afa
Show file tree
Hide file tree
Showing 7 changed files with 707 additions and 146 deletions.
177 changes: 164 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ You may install the Bakame Url package with Composer (recommended) or manually.
```json
{
"require": {
"bakame/csv": "2.*"
"bakame/csv": "3.*"
}
}
```
Expand All @@ -40,45 +40,196 @@ The easiest way to get started is to add `'/path/to/Bakame/Csv/src'` to your PSR
Usage
-------

The wrapper serves 2 main functions loading and saving data in CSV formats. To do that, the wrapper always returns a `SplFileObject` instance with flags set to `SplFileObject::READ_CSV` so that you can use it to further manipulate your data.
Of course, since a `SplFileObject` is returned you are free to modify the flags to satisfy your application needs.
### The Codec Class.

The `Codec` class enable loading and saving data in CSV formats. The class returns a `Reader` class to use to further manipulate your data.

```php
<?php


use Bakame\Csv\Codec;

$codec = new Codec;
$codec->setDelimeter(',');
$codec->setEnclosure('"');
$codec->setEscape('\\');
```

#### `Codec::loadFile` and `Codec::loadString`

$file = $codec->loadFile('path/to/my/csv/file.csv');
//returns a SplFileObject object you can use to iterate throught your CSV data
Depending on your CSV source you may choose `Codec::loadFile` method or `Codec::loadString` to enable reading your CSV. Whatever source you chose both methods will return a `Bakame\Csv\Reader` object to help you manipulate your data.

$file = $codec->loadString(['foo,bar,baz', ['foo', 'bar', 'baz']]);
//returns a SplTempFileObject object you can use to iterate throught your CSV data
```php
$reader = $codec->loadFile('path/to/my/csv/file.csv');
//$reader is a Reader object

$reader = $codec->loadString(['foo,bar,baz', ['foo', 'bar', 'baz']]);
//$reader is a Reader object

```

To Save your data you can use the `save` method as shown below.
The method accepts:
#### `Codec::save`

This methods help you save you CSV data.
It accepts:

* an `array` of data
* any object that implements the `Traversable` interface.

The path to where the data must saved can be given as:
* a simple string
* an `SplFileInfo` instance

If for any reason the data or the file does not exist an `InvalidArgumentException` will be thrown by the class
If the data is invalid or the file does not exist or is not writable an `InvalidArgumentException` will be thrown by the class.
Just like the loading methods, the `Codec::save` returns a `Bakame\Csv\Reader` object.

```php

$reader = $codec->save([1,2,3,4], '/path/to/my/saved/csv/file.csv');
//returns a Reader object

```

### The Reader Class


The `Reader` facilitates manipulating CSV data that are stored in a `SplFileObject` object.
To instantiate the class you must provide at leat a `SplFileObject` object like below:

```php

use Bakame\Csv\Reader;

$file = new \SpliFileObject('/path/to/your/csv/file.csv');
$reader = new Reader($file);
$reader->setDelimeter(',');
$reader->setEnclosure('"');
$reader->setEscape('\\');

```
You can optionally set CSV delimiter, enclosure and/or escape characters.

The `Bakame\Csv\Reader` object let you access the `SplFileObject` used to instantiate it when using the method `Reader::getFile`. This method comes handy if, for instance, you want to download your data. But it also exposes several fetching methods to help you easily extract you CSV data:

#### `Reader::fetchAll`

This methods returns a sequentials array of all CSV rows.

```php
$data = $reader->fetchAll();
// will return something like this :
//
// [
// ['john', 'doe', '[email protected]'],
// ['jane', 'doe', '[email protected]'],
// ...
// ]
//
```
This method can take an optional callable variable to further manipulate each row before being returned. This callable expected an array as its sole argument.

```php
$data = $reader->fetchAll(function ($value) {
return array_map('strtoupper', $value);
});
// will return something like this :
//
// [
// ['JOHN', 'DOE', '[email protected]'],
// ['JANE', 'DOE', '[email protected]'],
// ...
// ]
//
```

#### `Reader::fetchAssoc`

This method returns a sequentials array of all CSV rows. the rows are associative arrays where the key are given to the method using a array.

```php
$data = $reader->fetchAssoc(['firstname', 'lastname', 'email']);
// will return something like this :
//
// [
// ['firstname' => 'john', 'lastname' => 'doe', 'email' => '[email protected]'],
// ['firstname' => 'jane', 'lastname' => 'doe', 'email' => '[email protected]'],
// ...
// ]
//
```
This method can take an optional callable variable to further manipulate each row before being returned. This callable expected an array as its sole argument.

```php
$data = $reader->fetchAssoc(['firstname', 'lastname', 'email'], function ($value) {
return array_map('strtoupper', $value);
});
// will return something like this :
//
// [
// ['firstname' => 'JOHN', 'lastname' => 'DOE', 'email' => '[email protected]'],
// ['firstname' => 'JANE', 'lastname' => 'DOE', 'email' => '[email protected]'],
// ...
// ]
//
```

$file = $codec->save([1,2,3,4], '/path/to/my/saved/csv/file.csv');
//returns a SplFileObject object to manage the newly saved data
#### `Reader::fetchCol`

This method returns an sequentials array for a given CSV column.

```php
$data = $reader->fetchCol(2);
// will return something like this :
//
// ['[email protected]', '[email protected]', ...]
//
```
This method can take an optional callable variable to further manipulate each value before being returned. This callable expected an array as its sole argument.

```php
$data = $reader->fetchCol(2, function ($value) {
return array_map('strtoupper', $value);
});
// will return something like this :
//
// ['[email protected]', '[email protected]', ...]
//
```

#### `Reader::fetchOne`

This method returns an array representing one CSV row given the row Index. the index starts at 0.

```php
$data = $reader->fetchOne(1);
// will return something like this :
//
// ['jane', 'doe', '[email protected]']
//
```

#### `Reader::fetchValue`

This method returns the value of a given field in a given row. If the value is not found it will return null.
The first argument represents the row and the second represents the column index. the 2 indexes starts at 0;
```php
$data = $reader->fetchValue(1, 2);
// will return something like this :
//
// '[email protected]'
//
```

#### `Reader::setFlags`

Sometimes you may wish to change the SplFileObject Flags. You can do so using the following method:

```php
$reader->setFlags(SplFileObject::READ_AHEAD|SplFileObject::SKIP_EMPTY);
```

It is important to used the reader method and **not** the file method as the `Reader` will always append the `SplFileObject::READ_CSV` flag.


Testing
-------
Expand Down
124 changes: 12 additions & 112 deletions src/Bakame/Csv/Codec.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* @copyright 2013 Ignace Nyamagana Butera
* @link https://github.com/nyamsprod/Bakame.csv
* @license http://opensource.org/licenses/MIT
* @version 2.0.0
* @version 3.0.0
* @package Bakame.csv
*
* MIT LICENSE
Expand Down Expand Up @@ -42,28 +42,12 @@
* A simple Coder/Decoder to ease CSV management in PHP 5.4+
*
* @package Bakame.csv
* @since 2.0
*
*/
class Codec
{
/**
* the field delimiter (one character only)
*
* @var string
*/
private $delimiter = ',';

/**
* the field enclosure character (one character only)
*
* @var string
*/
private $enclosure = '"';

/**
* the field escape character (one character only)
* @var string
*/
private $escape = '\\';
use CsvControlsTrait;

/**
* The constructor
Expand All @@ -79,93 +63,6 @@ public function __construct($delimiter = ',', $enclosure = '"', $escape = "\\")
$this->setEscape($escape);
}

/**
* set the field delimeter
*
* @param string $delimiter
*
* @return self
*
* @throws \InvalidArgumentException If $delimeter is not a single character
*/
public function setDelimiter($delimiter = ',')
{
if (1 != mb_strlen($delimiter)) {
throw new InvalidArgumentException('The delimiter must be a single character');
}
$this->delimiter = $delimiter;

return $this;
}

/**
* return the current field delimiter
*
* @return string
*/
public function getDelimiter()
{
return $this->delimiter;
}

/**
* set the field enclosure
*
* @param string $enclosure
*
* @return self
*
* @throws \InvalidArgumentException If $enclosure is not a single character
*/
public function setEnclosure($enclosure = '"')
{
if (1 != mb_strlen($enclosure)) {
throw new InvalidArgumentException('The enclosure must be a single character');
}
$this->enclosure = $enclosure;

return $this;
}

/**
* return the current field enclosure
*
* @return string
*/
public function getEnclosure()
{
return $this->enclosure;
}

/**
* set the field escape character
*
* @param string $escape
*
* @return self
*
* @throws \InvalidArgumentException If $escape is not a single character
*/
public function setEscape($escape = "\\")
{
if (1 != mb_strlen($escape)) {
throw new InvalidArgumentException('The escape character must be a single character');
}
$this->escape = $escape;

return $this;
}

/**
* return the current field escape character
*
* @return string
*/
public function getEscape()
{
return $this->escape;
}

/**
* Load a CSV string
*
Expand All @@ -177,10 +74,8 @@ public function loadString($str)
{
$file = new SplTempFileObject();
$file->fwrite($str);
$file->setFlags(SplFileObject::READ_CSV);
$file->setCsvControl($this->delimiter, $this->enclosure, $this->escape);

return $file;
return new Reader($file, $this->delimiter, $this->enclosure, $this->escape);
}

/**
Expand All @@ -192,7 +87,12 @@ public function loadString($str)
*/
public function loadFile($path, $mode = 'r')
{
return $this->create($path, $mode, ['r', 'r+', 'w+', 'x+', 'a+', 'c+']);
return new Reader(
$this->create($path, $mode, ['r', 'r+', 'w+', 'x+', 'a+', 'c+']),
$this->delimiter,
$this->enclosure,
$this->escape
);
}

/**
Expand All @@ -212,7 +112,7 @@ public function save($data, $path, $mode = 'w')
$file->fputcsv($row);
});

return $file;
return new Reader($file, $this->delimiter, $this->enclosure, $this->escape);
}

/**
Expand Down
Loading

0 comments on commit b278afa

Please sign in to comment.