Керування великими наборами даних у Laravel за допомогою Lazy Collection

Перекладено ШІ
Оригінал: Laravel News
Оновлено: 04 грудня, 2024
Під час обробки великих обсягів даних у додатках Laravel важливо ефективно управляти пам'яттю. Досліджуйте можливості LazyCollection – потужного інструмента, який дозволяє обробляти великі набори даних, завантажуючи лише необхідні елементи за допомогою простих рішень

При обробці великих обсягів даних у програмах Laravel важливо ефективно управляти пам'яттю. LazyCollection — це розумне рішення, яке дозволяє завантажувати дані за запитом, а не одночасно. Розгляньмо цю потужну функцію для ефективного опрацювання великих наборів даних.

# Що таке LazyCollection

LazyCollection, доступна з Laravel 6.0, дозволяє ефективно обробляти великі набори даних, завантажуючи елементи лише за необхідності. Це ідеальний інструмент для роботи з великими файлами або широкими запитами до бази даних без перевантаження пам'яті вашої програми.

use Illuminate\Support\LazyCollection;
 
LazyCollection::make(function () {
    $handle = fopen('data.csv', 'r');
    while (($row = fgets($handle)) !== false) {
        yield str_getcsv($row);
    }
})->each(function ($row) {
    // Обробка даних рядка
});

# Приклад використання LazyCollection

Розгляньмо практичний приклад, у якому ми обробляємо великий файл журналу транзакцій та генеруємо звіти:

<?php
namespace App\Services;
 
use App\Models\TransactionLog;
use Illuminate\Support\LazyCollection;
 
class TransactionProcessor
{
    public function processLogs(string $filename)
    {
        return LazyCollection::make(function () use ($filename) {
            $handle = fopen($filename, 'r');
 
            while (($line = fgets($handle)) !== false) {
                yield json_decode($line, true);
            }
        })
        ->map(function ($log) {
            return [
                'transaction_id' => $log['id'],
                'amount' => $log['amount'],
                'status' => $log['status'],
                'processed_at' => $log['timestamp']
            ];
        })
        ->filter(function ($log) {
            return $log['status'] === 'completed';
        })
        ->chunk(500)
        ->each(function ($chunk) {
            TransactionLog::insert($chunk->all());
        });
    }
}

З таким підходом ми можемо:

Для операцій з базою даних у Laravel є метод cursor(), який створює лінійні колекції:

<?php
 
namespace App\Http\Controllers;
 
use App\Models\Transaction;
use Illuminate\Support\Facades\DB;
 
class ReportController extends Controller
{
    public function generateReport()
    {
        DB::transaction(function () {
            Transaction::cursor()
                ->filter(function ($transaction) {
                    return $transaction->amount > 1000;
                })
                ->each(function ($transaction) {
                    // Обробка кожної великої транзакції
                    $this->processHighValueTransaction($transaction);
                });
        });
    }
}

Ця реалізація забезпечує ефективне використання пам'яті навіть при обробці мільйонів записів, що робить її ідеальною для фонових завдань та обробки даних