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;
});
