You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+38-13Lines changed: 38 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,10 +8,13 @@
8
8
9
9
## Why fluent iterators?
10
10
11
-
Flow provides a fluent interface to assemble chains of iterators and other data processing operations. Instead of
12
-
collecting values into arrays and managing nested `foreach` loops manually, you compose small, intention-revealing
13
-
operations that stream data from one step to the next. The expressive syntax makes it **easy and enjoyable** to build
14
-
sophisticated processing pipelines while keeping memory usage low and the intent of each transformation crystal clear.
11
+
PHP has a rich set of iterators and other data processing tools - like the iterators in the Standard PHP Library (SPL) - but they are often not used to their full potential, as they are cumbersome to use and require a lot of boilerplate code.
12
+
13
+
Flow provides a fluent interface to assemble chains of iterators and other data processing operations, making it easy to write complex data processing pipelines in a concise and readable way.
14
+
15
+
Instead of collecting values into arrays and managing nested `foreach` loops manually, you compose small, intention-revealing operations that stream data from one step to the next.
16
+
17
+
The expressive syntax makes it **easy and enjoyable** to build sophisticated processing pipelines while keeping **memory usage low** and the intent of each transformation crystal clear.
The same workflow using temporary arrays and for-loops would be longer, harder to read and would duplicate values in
35
-
memory multiple times. A Flow pipeline keeps the computation streaming, lets you re-use SPL iterators seamlessly and
36
-
makes experimentation as simple as inserting or removing a step.
37
+
The same workflow using temporary arrays and for-loops would be longer, harder to read and would duplicate values in memory multiple times.
38
+
39
+
A Flow pipeline keeps the computation streaming, lets you re-use SPL iterators seamlessly and makes experimentation as simple as inserting or removing a step.
37
40
38
41
## Flow is **not** the usual Collection-style utility library
39
42
40
-
Typical Collection-like classes use arrays underneath. But `Flow`, even though it also uses a chainable fluent interface, is both an `Iterator` and a `Traversable` (therefore with native PHP support), and works perfectly with **Generators** and **SPL iterators**, with no arrays underneath. **Each iteration step only requires one value to be in memory (it can be generated on the fly), and the data is streamed through the pipeline**.
43
+
Although many libraries exist for implementing collections (e.g. Laravel Collections), Flow is different, even though, on the surface, it seems similar, as it also provides a chainable fluent interface.
44
+
45
+
Typical Collection-like classes use arrays underneath. But Flow (most of the time) **does not**.
46
+
47
+
48
+
Flow is both an `Iterator` and a `Traversable` (therefore with native PHP support), and works perfectly with **Generators**, **SPL iterators** and `foreach` loops.
49
+
50
+
Each iteration step only requires **one value** to be in memory (and it can be generated on the fly), and the data is streamed through the pipeline, with **no intermediate storage** and **without needless data copying**.
41
51
42
-
Since Flow implements both `Iterator` and `Traversable`, you can use a Flow object anywhere you would use a `Traversable` or `Iterator`. For example, you can use `foreach` directly over a Flow object:
52
+
You can use a Flow object anywhere an `Iterator` or `Traversable` interface is expected.
53
+
For example, you can use `foreach` directly over a Flow object:
43
54
44
55
```php
45
56
foreach (Flow::from([1, 2, 3]) as $value) {
@@ -63,6 +74,21 @@ function processItems(Traversable $items) {
In this example, **the values are generated only when they are read, not when the flow is created**, which is a **major difference** from traditional collections.
87
+
88
+
This also means that if the iteration is not fully consumed, some values may not be generated at all. This lazy evaluation is particularly important when value generation is computationally expensive, as it avoids unnecessary computation.
89
+
90
+
Additionally, when processing very large datasets, Flow maintains minimal memory usage by processing values one at a time as they stream through the pipeline, rather than loading the entire dataset into memory.
| `FilesystemFlow::from(string $path, int $flags = FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::SKIP_DOTS)` | Streams directory entries with full control over SPL flags.
178
+
| `FilesystemFlow::from(string $path, int $flags = FilesystemIterator::KEY_AS_PATHNAME \| FilesystemIterator::CURRENT_AS_FILEINFO \| FilesystemIterator::SKIP_DOTS)` | Streams directory entries with full control over SPL flags.
153
179
| `FilesystemFlow::glob(string $pattern, int $flags = 0)` | Iterates filesystem matches similar to `glob()` but lazily.
154
180
| `FilesystemFlow::recursiveFrom(string $path, int $flags = FilesystemIterator::KEY_AS_PATHNAME \| FilesystemIterator::CURRENT_AS_FILEINFO \| FilesystemIterator::SKIP_DOTS, int $mode = RecursiveIteratorIterator::SELF_FIRST)` | Builds a recursive traversal using `RecursiveIteratorIterator` and a configurable recursion mode.
155
181
| `FilesystemFlow::recursiveGlob(string $rootDir, string $pattern, int $flags = 0)` | Performs recursive glob searches, yielding `SplFileInfo` objects or paths according to flags.
@@ -190,8 +216,7 @@ The `globals.php` helpers make it effortless to adopt Flow throughout an applica
190
216
191
217
## Notes
192
218
193
-
Some operations (such as `reverse()` or `sort()`) need to materialize the stream into an array before continuing. The
194
-
library only buffers data when absolutely necessary and automatically returns to streaming mode afterwards.
219
+
Some operations (such as `reverse()` or `sort()`) need to materialize the stream into an array before continuing. The library only buffers data when absolutely necessary and automatically returns to streaming mode afterwards.
0 commit comments