Skip to content

Commit b278afa

Browse files
committed
Merge pull request #2 from nyamsprod/develop
Adding the ReaderInterface
2 parents 8b003d0 + c3182d8 commit b278afa

File tree

7 files changed

+707
-146
lines changed

7 files changed

+707
-146
lines changed

README.md

Lines changed: 164 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ You may install the Bakame Url package with Composer (recommended) or manually.
2121
```json
2222
{
2323
"require": {
24-
"bakame/csv": "2.*"
24+
"bakame/csv": "3.*"
2525
}
2626
}
2727
```
@@ -40,45 +40,196 @@ The easiest way to get started is to add `'/path/to/Bakame/Csv/src'` to your PSR
4040
Usage
4141
-------
4242

43-
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.
44-
Of course, since a `SplFileObject` is returned you are free to modify the flags to satisfy your application needs.
43+
### The Codec Class.
44+
45+
The `Codec` class enable loading and saving data in CSV formats. The class returns a `Reader` class to use to further manipulate your data.
4546

4647
```php
4748
<?php
4849

49-
5050
use Bakame\Csv\Codec;
5151

5252
$codec = new Codec;
5353
$codec->setDelimeter(',');
5454
$codec->setEnclosure('"');
5555
$codec->setEscape('\\');
56+
```
57+
58+
#### `Codec::loadFile` and `Codec::loadString`
5659

57-
$file = $codec->loadFile('path/to/my/csv/file.csv');
58-
//returns a SplFileObject object you can use to iterate throught your CSV data
60+
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.
5961

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

6369
```
6470

65-
To Save your data you can use the `save` method as shown below.
66-
The method accepts:
71+
#### `Codec::save`
72+
73+
This methods help you save you CSV data.
74+
It accepts:
75+
6776
* an `array` of data
6877
* any object that implements the `Traversable` interface.
6978

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

74-
If for any reason the data or the file does not exist an `InvalidArgumentException` will be thrown by the class
83+
If the data is invalid or the file does not exist or is not writable an `InvalidArgumentException` will be thrown by the class.
84+
Just like the loading methods, the `Codec::save` returns a `Bakame\Csv\Reader` object.
85+
86+
```php
87+
88+
$reader = $codec->save([1,2,3,4], '/path/to/my/saved/csv/file.csv');
89+
//returns a Reader object
90+
91+
```
92+
93+
### The Reader Class
94+
95+
96+
The `Reader` facilitates manipulating CSV data that are stored in a `SplFileObject` object.
97+
To instantiate the class you must provide at leat a `SplFileObject` object like below:
98+
99+
```php
100+
101+
use Bakame\Csv\Reader;
102+
103+
$file = new \SpliFileObject('/path/to/your/csv/file.csv');
104+
$reader = new Reader($file);
105+
$reader->setDelimeter(',');
106+
$reader->setEnclosure('"');
107+
$reader->setEscape('\\');
108+
109+
```
110+
You can optionally set CSV delimiter, enclosure and/or escape characters.
111+
112+
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:
113+
114+
#### `Reader::fetchAll`
115+
116+
This methods returns a sequentials array of all CSV rows.
117+
118+
```php
119+
$data = $reader->fetchAll();
120+
// will return something like this :
121+
//
122+
// [
123+
// ['john', 'doe', 'john.doe@example.com'],
124+
// ['jane', 'doe', 'jane.doe@example.com'],
125+
// ...
126+
// ]
127+
//
128+
```
129+
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.
130+
131+
```php
132+
$data = $reader->fetchAll(function ($value) {
133+
return array_map('strtoupper', $value);
134+
});
135+
// will return something like this :
136+
//
137+
// [
138+
// ['JOHN', 'DOE', 'JOHN.DOE@EXAMPLE.COM'],
139+
// ['JANE', 'DOE', 'JANE.DOE@EXAMPLE.COM'],
140+
// ...
141+
// ]
142+
//
143+
```
144+
145+
#### `Reader::fetchAssoc`
146+
147+
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.
75148

76149
```php
150+
$data = $reader->fetchAssoc(['firstname', 'lastname', 'email']);
151+
// will return something like this :
152+
//
153+
// [
154+
// ['firstname' => 'john', 'lastname' => 'doe', 'email' => 'john.doe@example.com'],
155+
// ['firstname' => 'jane', 'lastname' => 'doe', 'email' => 'jane.doe@example.com'],
156+
// ...
157+
// ]
158+
//
159+
```
160+
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.
161+
162+
```php
163+
$data = $reader->fetchAssoc(['firstname', 'lastname', 'email'], function ($value) {
164+
return array_map('strtoupper', $value);
165+
});
166+
// will return something like this :
167+
//
168+
// [
169+
// ['firstname' => 'JOHN', 'lastname' => 'DOE', 'email' => 'JOHN.DOE@EXAMPLE.COM'],
170+
// ['firstname' => 'JANE', 'lastname' => 'DOE', 'email' => 'JANE.DOE@EXAMPLE.COM'],
171+
// ...
172+
// ]
173+
//
174+
```
77175

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

178+
This method returns an sequentials array for a given CSV column.
179+
180+
```php
181+
$data = $reader->fetchCol(2);
182+
// will return something like this :
183+
//
184+
// ['john.doe@example.com', 'jane.doe@example.com', ...]
185+
//
81186
```
187+
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.
188+
189+
```php
190+
$data = $reader->fetchCol(2, function ($value) {
191+
return array_map('strtoupper', $value);
192+
});
193+
// will return something like this :
194+
//
195+
// ['JOHN.DOE@EXAMPLE.COM', 'JANE.DOE@EXAMPLE.COM', ...]
196+
//
197+
```
198+
199+
#### `Reader::fetchOne`
200+
201+
This method returns an array representing one CSV row given the row Index. the index starts at 0.
202+
203+
```php
204+
$data = $reader->fetchOne(1);
205+
// will return something like this :
206+
//
207+
// ['jane', 'doe', 'jane.doe@example.com']
208+
//
209+
```
210+
211+
#### `Reader::fetchValue`
212+
213+
This method returns the value of a given field in a given row. If the value is not found it will return null.
214+
The first argument represents the row and the second represents the column index. the 2 indexes starts at 0;
215+
```php
216+
$data = $reader->fetchValue(1, 2);
217+
// will return something like this :
218+
//
219+
// 'jane.doe@example.com'
220+
//
221+
```
222+
223+
#### `Reader::setFlags`
224+
225+
Sometimes you may wish to change the SplFileObject Flags. You can do so using the following method:
226+
227+
```php
228+
$reader->setFlags(SplFileObject::READ_AHEAD|SplFileObject::SKIP_EMPTY);
229+
```
230+
231+
It is important to used the reader method and **not** the file method as the `Reader` will always append the `SplFileObject::READ_CSV` flag.
232+
82233

83234
Testing
84235
-------

src/Bakame/Csv/Codec.php

Lines changed: 12 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* @copyright 2013 Ignace Nyamagana Butera
77
* @link https://github.com/nyamsprod/Bakame.csv
88
* @license http://opensource.org/licenses/MIT
9-
* @version 2.0.0
9+
* @version 3.0.0
1010
* @package Bakame.csv
1111
*
1212
* MIT LICENSE
@@ -42,28 +42,12 @@
4242
* A simple Coder/Decoder to ease CSV management in PHP 5.4+
4343
*
4444
* @package Bakame.csv
45+
* @since 2.0
46+
*
4547
*/
4648
class Codec
4749
{
48-
/**
49-
* the field delimiter (one character only)
50-
*
51-
* @var string
52-
*/
53-
private $delimiter = ',';
54-
55-
/**
56-
* the field enclosure character (one character only)
57-
*
58-
* @var string
59-
*/
60-
private $enclosure = '"';
61-
62-
/**
63-
* the field escape character (one character only)
64-
* @var string
65-
*/
66-
private $escape = '\\';
50+
use CsvControlsTrait;
6751

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

82-
/**
83-
* set the field delimeter
84-
*
85-
* @param string $delimiter
86-
*
87-
* @return self
88-
*
89-
* @throws \InvalidArgumentException If $delimeter is not a single character
90-
*/
91-
public function setDelimiter($delimiter = ',')
92-
{
93-
if (1 != mb_strlen($delimiter)) {
94-
throw new InvalidArgumentException('The delimiter must be a single character');
95-
}
96-
$this->delimiter = $delimiter;
97-
98-
return $this;
99-
}
100-
101-
/**
102-
* return the current field delimiter
103-
*
104-
* @return string
105-
*/
106-
public function getDelimiter()
107-
{
108-
return $this->delimiter;
109-
}
110-
111-
/**
112-
* set the field enclosure
113-
*
114-
* @param string $enclosure
115-
*
116-
* @return self
117-
*
118-
* @throws \InvalidArgumentException If $enclosure is not a single character
119-
*/
120-
public function setEnclosure($enclosure = '"')
121-
{
122-
if (1 != mb_strlen($enclosure)) {
123-
throw new InvalidArgumentException('The enclosure must be a single character');
124-
}
125-
$this->enclosure = $enclosure;
126-
127-
return $this;
128-
}
129-
130-
/**
131-
* return the current field enclosure
132-
*
133-
* @return string
134-
*/
135-
public function getEnclosure()
136-
{
137-
return $this->enclosure;
138-
}
139-
140-
/**
141-
* set the field escape character
142-
*
143-
* @param string $escape
144-
*
145-
* @return self
146-
*
147-
* @throws \InvalidArgumentException If $escape is not a single character
148-
*/
149-
public function setEscape($escape = "\\")
150-
{
151-
if (1 != mb_strlen($escape)) {
152-
throw new InvalidArgumentException('The escape character must be a single character');
153-
}
154-
$this->escape = $escape;
155-
156-
return $this;
157-
}
158-
159-
/**
160-
* return the current field escape character
161-
*
162-
* @return string
163-
*/
164-
public function getEscape()
165-
{
166-
return $this->escape;
167-
}
168-
16966
/**
17067
* Load a CSV string
17168
*
@@ -177,10 +74,8 @@ public function loadString($str)
17774
{
17875
$file = new SplTempFileObject();
17976
$file->fwrite($str);
180-
$file->setFlags(SplFileObject::READ_CSV);
181-
$file->setCsvControl($this->delimiter, $this->enclosure, $this->escape);
18277

183-
return $file;
78+
return new Reader($file, $this->delimiter, $this->enclosure, $this->escape);
18479
}
18580

18681
/**
@@ -192,7 +87,12 @@ public function loadString($str)
19287
*/
19388
public function loadFile($path, $mode = 'r')
19489
{
195-
return $this->create($path, $mode, ['r', 'r+', 'w+', 'x+', 'a+', 'c+']);
90+
return new Reader(
91+
$this->create($path, $mode, ['r', 'r+', 'w+', 'x+', 'a+', 'c+']),
92+
$this->delimiter,
93+
$this->enclosure,
94+
$this->escape
95+
);
19696
}
19797

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

215-
return $file;
115+
return new Reader($file, $this->delimiter, $this->enclosure, $this->escape);
216116
}
217117

218118
/**

0 commit comments

Comments
 (0)