Despre metoda chunck() in Laravel

postat acum un an de Stefanescu Mihai in categorie iNoob

Hai sa ne imaginam urmatoarea situatie: Avem un tabel dintr-o baza de date cu peste 10 000 de randurisi trebuie sa facem un update unei singure coloane. Si in mod evident trebuie sa facem asta in PHP, nu putem pur si simplu rula un query. Deci, facand asta putem intampina urmatoarele probleme...ori codul nostru va dura o eternitate si jumatate pana cand va rula, ori vom primi eroare de max execution time (adica a durat mult prea mult).

Spre bucuria noastra, Laravel a venit cu o solutie interesanta pentru aceasta problema.

Hai sa luam un exemplu concret:

$users = User::all();
foreach ($users as $user) {
  $o_valoare = ($user->un_camp > 0) ? 1 : 0;
  $user->update(['un_oarecare_camp' => $o_valoare]);
}

Bineinteles, daca avem un tabel cu 100 de randuri, sau 500, sau chiar 1000...nu avem probleme.Dar, ce se intampla cand avem 10000 de randuri? Sau poate chair 100000? In acest caz deja nu se mai pune problema de durata, ba chiar am putea ramane fara memorie (presupunand ca stocam aceste randuri intr-o avriabila).

Aici ne sare in ajutor laravel, venind cu o functie numita chunk() ce imparte datele in selecturi separate, cum face si pagination().

Hai sa vedem un exemplu:

User::chunk(100, function ($users) {
  foreach ($users as $user) {
    $o_valoare = ($user->un_camp > 0) ? 1 : 0;
    $user->update(['un_oarecare_camp' => $o_valoare]);
  }
});

Ce face de fapt aceasta functie? Ruleaza un loop ce selecteaza de fiecare data cand este rulata cate 100 de randuri, dupa care ruleaza update-ul din foreach. In acest mod nu mai avem problema de mai sus pentru ca lucram numai cu cate 100 de randuri, nu cu toate randurile din tabel.

Vreau sa va avertizez sa aveti grija la filtrarea rezultatelor:

User::where('status', 0)->chunk(100, function ($users) {
  foreach ($users as $user) {
    $user->update(['status' => 1]);
  }
});

Tehnic vorbind, chestia asta va functiona si nu va va data nici-o eroare, dar problema ar putea fi ca filtrezi utilizatorii cu status 0, si le schimbi statusul, iar la urmatoare rulare a lui chunk() datelor vor fi deja schimbate, ceea ce va avea efectul ca la sfarsit numai jumatate din date vor fi modificate. Ce va sfatuiesc eu? Sa nu updata-ti aceaqlsi camp dupa care faceti filtrarea.

Sunt un tanar programator din Bucuresti ce lucreaza in PHP/Mysql (MySqli/PDO), Laravel, CodeIgniter, MySQL, PostgreSQL, Wordpress, HTML5/CSS3, Sass, Photoshop si multe altele.
Google+ Community Facebook Group