PHPExcel освобождает память после сохранения файла Excel - PullRequest
1 голос
/ 06 апреля 2020

Этот код предназначен для хранения сгенерированного файла Excels с PHP библиотекой Excel

"maatwebsite / excel": "~ 2.1.0"

Есть 30 КБ строки данных транзакции, и каждая транзакция имеет под-данные. Цель состоит в том, чтобы создать документ отчета о транзакциях, который группируется по месяцам (1 месяц = ​​1 файл Excel). 15k транзакций было установлено как ограничение на лист (оно автоматически генерирует новый лист, если лимит был превышен).

Поскольку я пытался регистрировать использование памяти, процесс занял загрузку памяти , Вот следующие сведения об использовании памяти.

Первое состояние памяти: 10 МБ

Первый файл Excel (первый месяц) Сгенерированное состояние памяти: 88 МБ

Ожидаемое состояние памяти после сохранения первого файла Excel: аналогично первому состоянию 10 МБ

Фактическое состояние памяти после сохранения первого файла Excel: 60 МБ

Это означает, что phpexcel не полностью освободил память даже после того, как первый файл имеет

Предположительно PHP excel должен освободить память после того, как был создан первый файл. Цель состоит в том, чтобы сгенерировать как минимум 150 тыс. Строк транзакций в отдельных файлах Excel, но в этой ситуации я считаю, что это невозможно, поскольку потребуется много памяти.

Любое решение, которое можно сделать, чтобы избежать проблем с памятью при генерации PHP файлов Excel?

Код, который используется для генерации файлов Excel, показан ниже. Заранее спасибо.

    $counter = 0;
    // Loop through months
    foreach ($period as $month) {
        $numberOfPages = 1;
        $startOfMonth = $monthLoops === 0 ? Carbon::parse($export->startDate) : $month->copy()->startOfMonth();
        $endOfMonth = $monthLoops === $numberOfMonths ? Carbon::parse($export->endDate) : $month->copy()->endOfmonth();
        $monthName = $month->format('F');

        // do the first call and get number of records and calculate pages
        list($transactions, $aggregations, $numberOfTransactions) = $this->getTransactionsCall($datalakeSalesTransactionRepository, $companyUuid, $export, $startOfMonth, $endOfMonth, 1, 1, null, 1);

        if ($transactions) {
            // generate first datalake excel call
            $objPHPExcel = Excel::create("Laporan Transaksi Penjualan $monthName ".$startOfMonth->year, function ($excel) use ($export, &$counter, $totalTransactionsPerSheet, $numberOfPages, $datalakeSalesTransactionRepository, $companyUuid, $startOfMonth, $endOfMonth, $perPage, $transactions, $aggregations, $numberOfTransactions) {
                $page = 1;
                // calculate pages and sheets
                $sheetLoop = 1;
                $numberOfPages = $numberOfTransactions !== 0 ? (int) ceil($numberOfTransactions/$perPage) : 1;
                $numberOfSheets =$numberOfTransactions !== 0 ? (int) ceil($numberOfTransactions/$totalTransactionsPerSheet) : 1;

                // generate all sheets in one excel
                for ($sheetLoop; $sheetLoop <= $numberOfSheets; $sheetLoop++) {
                    // generate sheets if total of transactions in one excel exceed limit of totalRows per sheet chunk by perPage
                    $this->currentRow = 1;
                    $numberOfTransactionsInOneSheet = 0;

                    $excel->sheet("$export->myTitle-$sheetLoop", function ($sheet) use ($export, $aggregations, $numberOfTransactionsInOneSheet, &$counter, $totalTransactionsPerSheet, &$page, $numberOfPages, $datalakeSalesTransactionRepository, $companyUuid, $startOfMonth, $endOfMonth, $perPage) {
                        // loop through calls per 200 items to avoid memory usage issue
                        $header = $this->getHeader($export, $startOfMonth, $endOfMonth);

                        foreach ($header as $row) {
                            $sheet->row($this->currentRow++, $row);
                        }

                        while ($page <= $numberOfPages) {
                            $transactions = $this->getTransactionsCall($datalakeSalesTransactionRepository, $companyUuid, $export, $startOfMonth, $endOfMonth, $page, $perPage, 1);

                            foreach ($transactions as $keyTrx => $transaction) {
                                $counter++;
                                $this->generateRow($transaction, $keyTrx, $sheet);
                                \Log::info(array('transactions' => $counter, $startOfMonth->month));
                                \Log::info(memory_get_usage()/1000000);
                            }


                            $numberOfTransactionsInOneSheet += $perPage;
                            $page++;

                            if ($numberOfTransactionsInOneSheet >= $totalTransactionsPerSheet) {
                                break;
                            }
                        }

                        $this->setTotal($aggregations);
                        $this->setUpSheet($sheet);
                    });
                }

                $this->getDatalakeDownpaymentSheet($excel, $export, $companyUuid, $numberOfPages, $perPage, $startOfMonth, $endOfMonth, $datalakeSalesTransactionRepository);
                $excel->setActiveSheetIndex(0);
            });

            $objPHPExcel->store($export->extension, $folderPath);

            $objPHPExcel->disconnectWorksheets();
            $objPHPExcel->garbageCollect();
            unset($objPHPExcel);
        }

        $monthLoops++;
    }

Я пытался освободить память после того, как файл был сохранен с этими частями кода, но, похоже, он не работает.

        $objPHPExcel->store($export->extension, $folderPath);

        $objPHPExcel->disconnectWorksheets();
        $objPHPExcel->garbageCollect();
        unset($objPHPExcel);
...