Skip to content

Commit 5558f9d

Browse files
committed
Simplify Reader and Writer instantiation
1 parent 7fce732 commit 5558f9d

33 files changed

+445
-246
lines changed

CHANGELOG.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,29 @@
22

33
All Notable changes to `Csv` will be documented in this file
44

5+
## [Next](https://github.com/thephpleague/csv/compare/9.26.0...master) - TBD
6+
7+
### Added
8+
9+
- `AbstractCsv::from` and `AbstractCsv::fromString` to simplify instantiating `Reader` and `Writer` instance.
10+
- `Stream::from` and `Stream::fromString` to simplify internal instantiation of `Stream` instances.
11+
12+
### Deprecated
13+
14+
- `AbstractCsv::createFromString` use `AbstractCsv::fromString` instead
15+
- `AbstractCsv::createFromStream` use `AbstractCsv::from` instead
16+
- `AbstractCsv::createFromFileObject` use `AbstractCsv::from` instead
17+
- `Stream::createFromResource` use `Stream::from` instead
18+
- `Stream::createFromString` use `Stream::fromString` instead
19+
20+
### Fixed
21+
22+
- `None
23+
24+
### Remove
25+
26+
- None
27+
528
## [9.26.0](https://github.com/thephpleague/csv/compare/9.25.0...9.26.0) - 2025-10-01
629

730
### Added

docs/9.0/connections/instantiation.md

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,84 @@ title: Loading CSV documents
55

66
# Document loading
77

8-
Because CSV documents come in different forms we use named constructors to offer several ways to load them.
8+
Because CSV documents come in different forms, we use named constructors to offer several ways to load them.
99

10+
## Modern instantiation public API
11+
12+
<p class="message-notice">This new API is introduced in version <code>9.27.0</code></p>
13+
14+
### Loading from a string
15+
16+
```php
17+
public static AbstractCsv::fromString(string $content = ''): self
18+
```
19+
20+
Create a new object from a given string.
21+
22+
```php
23+
use League\Csv\Reader;
24+
use League\Csv\Writer;
25+
26+
$reader = Reader::fromString('john,doe,[email protected]');
27+
$writer = Writer::fromString('john,doe,[email protected]');
28+
```
29+
30+
<p class="message-notice">The <code>$content</code> argument default value is an empty string to ease usage.</p>
31+
32+
## Loading from a file or a stream
33+
34+
```php
35+
public static AbstractCsv::from(
36+
SplFileInfo|SplFileObject|resource|string $filename,
37+
string $mode = 'r+',
38+
resource $context = null
39+
): self
40+
```
41+
42+
If an `string` or a `SplFileInfo` object is given as the `$filename` argument, a new instance
43+
is created *à la* `fopen` and the `$mode` and the `$context` parameters are taking into account.
44+
45+
Otherwise, when a stream resource or an `SplFileObject` instance is given both arguments are
46+
ignored.
47+
48+
<div class="message-notice">Since version <code>9.27.0</code> the following methods are <strong>deprecated</strong>:
49+
<ul>
50+
<li><code>createFromPath()</code></li>
51+
<li><code>createFromStream()</code></li>
52+
<li><code>createFromFileObject()</code></li>
53+
</ul>
54+
</div>
55+
56+
```php
57+
use League\Csv\Reader;
58+
use League\Csv\Writer;
59+
60+
$reader = Reader::from('/path/to/your/csv/file.csv', 'r');
61+
$writer = Writer::from('/path/to/your/csv/file.csv', 'w');
62+
63+
$reader = Reader::from(fopen('/path/to/the/file.csv', 'r+'));
64+
$writer = Writer::from(tmpfile());
65+
66+
$reader = Reader::from(new SplFileInfo('/path/to/your/csv/file.csv'));
67+
$writer = Writer::from(new SplTempFileObject());
68+
```
69+
70+
<div class="message-notice">
71+
The <code>$mode</code> argument defaults to:
72+
<ul>
73+
<li><code>r+</code> for the <code>Writer</code> class</li>
74+
<li><code>r</code> for the <code>Reader</code> class</li>
75+
</ul>
76+
</div>
77+
78+
<p class="message-notice">The method allows loading non-seekable stream resource.</p>
79+
80+
## Deprecated public API
81+
82+
<p class="message-warning">The following methods are all deprecated as of version <code>9.27.0</code></p>
1083
<p class="message-warning">Since version <code>9.1.0</code> non-seekable CSV documents can be used but <strong>exceptions will be thrown if features requiring a seekable CSV document are used.</strong></p>
1184

12-
## Loading from a string
85+
### Loading from a string
1386

1487
```php
1588
public static AbstractCsv::createFromString(string $content = ''): self
@@ -27,7 +100,7 @@ $writer = Writer::createFromString('john,doe,[email protected]');
27100

28101
<p class="message-notice">Since version <code>9.2.0</code> the <code>$content</code> argument default value is an empty string to ease usage.</p>
29102

30-
## Loading from a file path
103+
### Loading from a file path
31104

32105
```php
33106
public static AbstractCsv::createFromPath(
@@ -55,7 +128,7 @@ Starting with version <code>9.1.0</code>, <code>$open_mode</code> defaults to:
55128
</ul>
56129
</div>
57130

58-
## Loading from a resource stream
131+
### Loading from a resource stream
59132

60133
```php
61134
public static AbstractCsv::createFromStream(resource $stream): self
@@ -73,7 +146,7 @@ $writer = Writer::createFromStream(tmpfile());
73146

74147
<p class="message-notice">Prior to version <code>9.1.0</code>, the method would throw a <code>League\Csv\Exception</code> for a non-seekable stream resource.</p>
75148

76-
## Loading from a SplFileObject object
149+
### Loading from a SplFileObject object
77150

78151
```php
79152
public static AbstractCsv::createFromFileObject(SplFileObject $file): self
@@ -103,8 +176,8 @@ Once instantiated, the `getPathname` method returns the pathname of the underlyi
103176
use League\Csv\Reader;
104177
use League\Csv\Writer;
105178

106-
Reader::createFromFileObject(new SplFileObject('/path/to/your/csv/file.csv'))->getPathname();
179+
Reader::from(new SplFileObject('/path/to/your/csv/file.csv'))->getPathname();
107180
//returns '/path/to/your/csv/file.csv'
108-
Writer::createFromFileObject(new SplTempFileObject())->getPathname();
181+
Writer::from(new SplTempFileObject())->getPathname();
109182
//returns php://temp
110183
```

src/AbstractCsv.php

Lines changed: 76 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,16 @@
1818
use Generator;
1919
use InvalidArgumentException;
2020
use RuntimeException;
21+
use SplFileInfo;
2122
use SplFileObject;
2223
use Stringable;
2324
use Throwable;
25+
use TypeError;
2426

2527
use function filter_var;
2628
use function get_class;
29+
use function gettype;
30+
use function is_resource;
2731
use function rawurlencode;
2832
use function sprintf;
2933
use function str_replace;
@@ -79,42 +83,30 @@ public function __clone()
7983
throw UnavailableStream::dueToForbiddenCloning(static::class);
8084
}
8185

82-
/**
83-
* Returns a new instance from a SplFileObject.
84-
*/
85-
public static function createFromFileObject(SplFileObject $file): static
86-
{
87-
return new static($file);
88-
}
89-
90-
/**
91-
* Returns a new instance from a PHP resource stream.
92-
*
93-
* @param resource $stream
94-
*/
95-
public static function createFromStream($stream): static
96-
{
97-
return new static(Stream::createFromResource($stream));
98-
}
99-
10086
/**
10187
* Returns a new instance from a string.
10288
*/
103-
public static function createFromString(Stringable|string $content = ''): static
89+
public static function fromString(Stringable|string $content = ''): static
10490
{
105-
return new static(Stream::createFromString($content));
91+
return new static(Stream::fromString($content));
10692
}
10793

10894
/**
10995
* Returns a new instance from a file path.
11096
*
111-
* @param resource|null $context the resource context
97+
* @param SplFileInfo|SplFileObject|resource|string $filename an SPL file object, a resource stream or a file path
98+
* @param non-empty-string $mode the file path open mode used with a file path or a SplFileInfo object
99+
* @param resource|null $context the resource context used with a file pathor a SplFileInfo object
112100
*
113101
* @throws UnavailableStream
114102
*/
115-
public static function createFromPath(string $path, string $open_mode = 'r+', $context = null): static
103+
public static function from($filename, string $mode = 'r+', $context = null): static
116104
{
117-
return new static(Stream::createFromPath($path, $open_mode, $context));
105+
return match (true) {
106+
$filename instanceof SplFileObject => new static($filename),
107+
$filename instanceof SplFileInfo => new static($filename->openFile(mode: $mode, context: $context)),
108+
default => new static(Stream::from($filename, $mode, $context)),
109+
};
118110
}
119111

120112
/**
@@ -621,4 +613,65 @@ public function addStreamFilter(string $filtername, ?array $params = null): stat
621613

622614
return $this->appendStreamFilterOnWrite($filtername, $params);
623615
}
616+
617+
/**
618+
* DEPRECATION WARNING! This method will be removed in the next major point release.
619+
* @codeCoverageIgnore
620+
* @deprecated since version 9.27.0
621+
*
622+
* Returns a new instance from a SplFileObject.
623+
*/
624+
#[Deprecated(message:'use League\Csv\AbstractCsv::from() instead', since:'league/csv:9.27.0')]
625+
public static function createFromFileObject(SplFileObject $file): static
626+
{
627+
return new static($file);
628+
}
629+
630+
/**
631+
* DEPRECATION WARNING! This method will be removed in the next major point release.
632+
* @codeCoverageIgnore
633+
* @deprecated since version 9.27.0
634+
*
635+
* Returns a new instance from a PHP resource stream.
636+
*
637+
* @param resource $stream
638+
*/
639+
#[Deprecated(message:'use League\Csv\AbstractCsv::from() instead', since:'league/csv:9.27.0')]
640+
public static function createFromStream($stream): static
641+
{
642+
is_resource($stream) || throw new TypeError('Argument passed must be a stream resource or a string, '.gettype($stream).' given.');
643+
644+
return new static(Stream::from($stream));
645+
}
646+
647+
/**
648+
* DEPRECATION WARNING! This method will be removed in the next major point release.
649+
* @codeCoverageIgnore
650+
* @deprecated since version 9.27.0
651+
*
652+
* Returns a new instance from a string.
653+
*/
654+
#[Deprecated(message:'use League\Csv\AbstractCsv::fromString() instead', since:'league/csv:9.27.0')]
655+
public static function createFromString(Stringable|string $content = ''): static
656+
{
657+
return self::fromString($content);
658+
}
659+
660+
/**
661+
* DEPRECATION WARNING! This method will be removed in the next major point release.
662+
* @codeCoverageIgnore
663+
* @deprecated since version 9.27.0
664+
*
665+
* Returns a new instance from a file path.
666+
*
667+
* @param non-empty-string $open_mode
668+
* @param resource|null $context the resource context
669+
*
670+
* @throws UnavailableStream
671+
*/
672+
#[Deprecated(message:'use League\Csv\AbstractCsv::from() instead', since:'league/csv:9.27.0')]
673+
public static function createFromPath(string $path, string $open_mode = 'r+', $context = null): static
674+
{
675+
return new static(Stream::from($path, $open_mode, $context));
676+
}
624677
}

0 commit comments

Comments
 (0)