Mechanizm Lazy Collections, został wdrożony przez Josepha Silbera i jest to jedna z moich ulubionych nowych funkcji Laravel 6.
Dzięki zastosowaniu tego mechanizmu, możemy zoptymalizować pracę z obszernymi zbiorami danych, w tym kolekcji danych z Eloquenta. Nowa klasa "Illuminate\Support\LazyCollection" wykorzystuje generatory języka PHP by utrzymać niskie zużycie pamięci podczas pracy z ogromnymi zbiorami danych.
Dla przykładu: wyobraź sobie, że twoja aplikacja potrzebuje przetworzyć listę projektów która ma wiele gigabajtów. Używając Lazy Collection możesz przetworzyć tylko małą porcję pliku w pamięci w danym czasie.
use App\Project; use Illuminate\Support\LazyCollection; Route::get('/', function () { LazyCollection::make(function () { // projects.csv with 300.000 rows $filePath = storage_path('projects.csv'); $handle = fopen($filePath, 'r'); while ($line = fgetcsv($handle)) { yield $line; } }) ->chunk(10000) //split in chunk to reduce the number of queries ->each(function ($lines) { $list = []; foreach ($lines as $line) { if (isset($line[1])) { $list[] = [ 'name' => $line[1], 'email' => $line[2], 'status_id' => $line[3] ]; } } // insert 10000 rows in one shot Project::insert($list); }); });
Lub musisz przeiterować 10 000 modeli Eloquenta. Używając tradycyjnych metod kolekcji wszystkie modele musiałyby zostać załadowane w tym samym czasie...
$users = App\User::all()->filter(function ($user) { return $user->id > 500; });
Laravel 6 posiada metodę "cursor" w Query Buider, która wykorzystuje mechanizm Lazy Collection i zwraca instancję klasy LazyCollection. Metoda "cursor" pozwala na wykonanie pojedynczego zapytania do bazy danych i równocześnie trzymanie tylko jednego modelu Eloquenta w pamięci w danym czasie. Dla przykładu, metoda filter nie zostanie wykonana aż każdy user nie zostanie przeiterowany indywidualnie.
$users = App\User::cursor()->filter(function ($user) { return $user->id > 500; });