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
-[Retrieving Single Models / Aggregates](#retrieving-single-models)
@@ -318,9 +319,11 @@ In addition to the methods provided by Laravel's base collection class, the Eloq
318
319
319
320
Since all of Laravel's collections implement PHP's iterable interfaces, you may loop over collections as if they were an array:
320
321
321
-
foreach ($flights as $flight) {
322
-
echo $flight->name;
323
-
}
322
+
```php
323
+
foreach ($flights as $flight) {
324
+
echo $flight->name;
325
+
}
326
+
```
324
327
325
328
<aname="chunking-results"></a>
326
329
### Chunking Results
@@ -329,47 +332,84 @@ Your application may run out of memory if you attempt to load tens of thousands
329
332
330
333
The `chunk` method will retrieve a subset of Eloquent models, passing them to a closure for processing. Since only the current chunk of Eloquent models is retrieved at a time, the `chunk` method will provide significantly reduced memory usage when working with a large number of models:
331
334
332
-
use App\Models\Flight;
335
+
```php
336
+
use App\Models\Flight;
333
337
334
-
Flight::chunk(200, function ($flights) {
335
-
foreach ($flights as $flight) {
336
-
//
337
-
}
338
-
});
338
+
Flight::chunk(200, function ($flights) {
339
+
foreach ($flights as $flight) {
340
+
//
341
+
}
342
+
});
343
+
```
339
344
340
345
The first argument passed to the `chunk` method is the number of records you wish to receive per "chunk". The closure passed as the second argument will be invoked for each chunk that is retrieved from the database. A database query will be executed to retrieve each chunk of records passed to the closure.
341
346
342
347
If you are filtering the results of the `chunk` method based on a column that you will also be updating while iterating over the results, you should use the `chunkById` method. Using the `chunk` method in these scenarios could lead to unexpected and inconsistent results. Internally, the `chunkById` method will always retrieve models with an `id` column greater than the last model in the previous chunk:
343
348
344
-
Flight::where('departed', true)
345
-
->chunkById(200, function ($flights) {
346
-
$flights->each->update(['departed' => false]);
347
-
}, $column = 'id');
349
+
```php
350
+
Flight::where('departed', true)
351
+
->chunkById(200, function ($flights) {
352
+
$flights->each->update(['departed' => false]);
353
+
}, $column = 'id');
354
+
```
355
+
356
+
<aname="streaming-results-lazily"></a>
357
+
### Streaming Results Lazily
358
+
359
+
The `lazy()` method works similarly to [the `chunk` method](#chunking-results), executing the query in chunks. However, instead of passing each chunk into a callback, the `lazy()` method returns [a `LazyCollection`](/docs/{{version}}/collections#lazy-collections) of Eloquent models, which lets you interact with the results as a single stream:
360
+
361
+
```php
362
+
use App\Models\Flight;
363
+
364
+
foreach (Flight::lazy() as $flight) {
365
+
//
366
+
}
367
+
```
368
+
369
+
Once again, if you are filtering the results based on a column that you will also be updating while iterating over the results, you should use the `lazyById` method. Internally, the `lazyById` method will always retrieve models with an `id` column greater than the last model in the previous chunk:
370
+
371
+
```php
372
+
Flight::where('departed', true)
373
+
->lazyById(200, $column = 'id')
374
+
->each->update(['departed' => false]);
375
+
```
348
376
349
377
<aname="cursors"></a>
350
378
### Cursors
351
379
352
-
Similar to the `chunk` method, the `cursor` method may be used to significantly reduce your application's memory consumption when iterating through tens of thousands of Eloquent model records.
380
+
Similar to the `lazy` method, the `cursor` method may be used to significantly reduce your application's memory consumption when iterating through tens of thousands of Eloquent model records.
353
381
354
-
The `cursor` method will only execute a single database query; however, the individual Eloquent models will not be hydrated until they are actually iterated over. Therefore, only one Eloquent model is kept in memory at any given time while iterating over the cursor. Internally, the `cursor` method uses PHP [generators](https://www.php.net/manual/en/language.generators.overview.php) to implement this functionality:
382
+
The `cursor` method will only execute a single database query; however, the individual Eloquent models will not be hydrated until they are actually iterated over. Therefore, only one Eloquent model is kept in memory at any given time while iterating over the cursor.
355
383
356
-
use App\Models\Flight;
384
+
> {note} Since the `cursor` method only ever holds a single Eloquent model in memory at a time, it cannot eager load relationships. If you need to eager load models, consider using [the `lazy` method](#streaming-results-lazily) instead.
357
385
358
-
foreach (Flight::where('destination', 'Zurich')->cursor() as $flight) {
359
-
//
360
-
}
386
+
Internally, the `cursor` method uses PHP [generators](https://www.php.net/manual/en/language.generators.overview.php) to implement this functionality:
387
+
388
+
```php
389
+
use App\Models\Flight;
390
+
391
+
foreach (Flight::where('destination', 'Zurich')->cursor() as $flight) {
392
+
//
393
+
}
394
+
```
361
395
362
396
The `cursor` returns an `Illuminate\Support\LazyCollection` instance. [Lazy collections](/docs/{{version}}/collections#lazy-collections) allow you to use many of the collection methods available on typical Laravel collections while only loading a single model into memory at a time:
> {note} Although the `cursor` method uses far less memory than a regular query (by only holding a single Eloquent model in memory at a time), it will still eventually run out of memory. This is [due to PHP's PDO driver internally caching all raw query results in its buffer](https://www.php.net/manual/en/mysqlinfo.concepts.buffering.php).
411
+
>
412
+
> If you're dealing with an enormous amount of data, consider using [the `lazy` method](#streaming-results-lazily) instead.
@@ -154,6 +155,32 @@ If you are updating database records while chunking results, your chunk results
154
155
155
156
> {note} When updating or deleting records inside the chunk callback, any changes to the primary key or foreign keys could affect the chunk query. This could potentially result in records not being included in the chunked results.
156
157
158
+
<aname="streaming-results-lazily"></a>
159
+
### Streaming Results Lazily
160
+
161
+
The `lazy()` method works similarly to [the `chunk` method](#chunking-results), executing the query in chunks. However, instead of passing each chunk into a callback, the `lazy()` method returns [a `LazyCollection`](/docs/{{version}}/collections#lazy-collections), which lets you interact with the results as a single stream:
Once again, if you plan to update the retrieved records while iterating over them, it is best to use the `lazyById` method instead. This method will automatically paginate the results based on the record's primary key:
172
+
173
+
```php
174
+
DB::table('users')->where('active', false)
175
+
->lazyById()->each(function ($user) {
176
+
DB::table('users')
177
+
->where('id', $user->id)
178
+
->update(['active' => true]);
179
+
});
180
+
```
181
+
182
+
> {note} When updating or deleting records while iterating over them, any changes to the primary key or foreign keys could affect the chunk query. This could potentially result in records not being included in the results.
0 commit comments