File: rfc4180-field.md

package info (click to toggle)
php-league-csv 9.24.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 39,724 kB
  • sloc: php: 13,447; javascript: 80; makefile: 33; xml: 29
file content (125 lines) | stat: -rw-r--r-- 4,757 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
---
layout: default
title: CSV document interoperability
---

# RFC4180 Field compliance

<p class="message-warning">This class is deprecated as of version <code>9.2.0</code>. Please use the <code>setEscape</code> method directly with the empty escape character argument instead with the <code>Reader</code> or the <code>Writer</code> object.</p>

The `RFC4180Field` class enables to work around the following bugs in PHP's native CSV functions:

- [bug #43225](https://bugs.php.net/bug.php?id=43225): `fputcsv` incorrectly handles cells ending in `\` followed by `"`
- [bug #55413](https://bugs.php.net/bug.php?id=55413): `str_getcsv` doesn't remove escape characters
- [bug #74713](https://bugs.php.net/bug.php?id=74713): CSV cell split after `fputcsv()` + `fgetcsv()` round trip.
- [bug #38301](https://bugs.php.net/bug.php?id=38301): field enclosure behavior in `fputcsv` (since version `9.1.0`)

When using this stream filter you can easily create or read a [RFC4180 compliant CSV document](https://tools.ietf.org/html/rfc4180#section-2) using `League\Csv` connections objects.

<p class="message-warning">Changing the CSV objects control characters <strong>after registering the stream filter</strong> may result in unexpected returned records.</p>

## Usage with League\CSV objects

```php
public static RFC4180Field::addTo(AbstractCsv $csv, string $whitespace_replace = ''): AbstractCsv
```

The `RFC4180Field::addTo` method will register the stream filter if it is not already the case and add the stream filter to the CSV object using the following properties:

- the CSV enclosure property;
- the CSV escape property;
- the CSV stream filter mode;

```php
use League\Csv\RFC4180Field;
use League\Csv\Writer;

$writer = Writer::createFromPath('php://temp', 'r+');
$writer->setNewline("\r\n"); //RFC4180 Line feed
RFC4180Field::addTo($writer); //adding the stream filter to fix field formatting
$writer->insertAll($iterable_data);
$writer->output('mycsvfile.csv'); //outputting a RFC4180 compliant CSV Document
```

<p class="message-notice">the <code>$whitespace_replace</code> argument is available since version <code>9.1.0</code></p>

When the `$whitespace_replace` sequence is different from the empty space and does not contain:

- one of the current CSV control characters;
- a character that can trigger field enclosure;

its value will be used to:

- prevent `fputcsv` default behavior of always using enclosure when a whitespace is found in a record field

```php
use League\Csv\RFC4180Field;
use League\Csv\Writer;

$writer = Writer::createFromPath('php://temp', 'r+');
RFC4180Field::addTo($writer, "\0");
$writer->insertOne(['foo bar', 'bar']);
echo $writer->getContent(); //display 'foo bar,bar' instead of '"foo bar",bar'
```

<p class="message-warning">The <code>$whitespace_replace</code> sequence should be a sequence not present in the inserted records, otherwise your CSV content will be affected by it.</p>

```php
use League\Csv\RFC4180Field;
use League\Csv\Writer;

$writer = Writer::createFromPath('php://temp', 'r+');
RFC4180Field::addTo($writer, 'fo'); //incorrect sequence this will alter your CSV
$writer->insertOne(['foo bar', 'bar']);
echo $writer->getContent(); //display ' o bar,baz' instead of 'foo bar,baz'
```

### On records insertion

<p class="message-info">To fully comply with <code>RFC4180</code> you will also need to use <code>League\Csv\Writer::setNewline</code>.</p>

### On records extraction

Conversely, to read a RFC4180 compliant CSV document, when using the `League\Csv\Reader` object, you just need to add the `League\Csv\RFC4180Field` stream filter as shown below:

```php
use League\Csv\Reader;
use League\Csv\RFC4180Field;

//the current CSV is ISO-8859-15 encoded with a ";" delimiter
$csv = Reader::createFromPath('/path/to/rfc4180-compliant.csv', 'r');
RFC4180Field::addTo($csv); //adding the stream filter to fix field formatting

foreach ($csv as $record) {
    //do something meaningful here...
}
```

## Usage with PHP stream resources

```php
public static RFC4180Field::register(): void
public static RFC4180Field::getFiltername(): string
```

To use this stream filter outside `League\Csv` objects you need to:

- register the stream filter using `RFC4180Field::register`.
- use `RFC4180Field::getFiltername` with one of PHP's attaching stream filter functions with the correct arguments as shown below:

```php
use League\Csv\RFC4180Field;

RFC4180Field::register();

$resource = fopen('/path/to/my/file', 'r');
$filter = stream_filter_append($resource, RFC4180Field::getFiltername(), STREAM_FILTER_READ, [
    'enclosure' => '"',
    'escape' => '\\',
    'mode' => STREAM_FILTER_READ,
]);

while (false !== ($record = fgetcsv($resource))) {
    //$record is correctly parsed
}
```