PHP скрипт, генерирующий файл Excel, занимающий слишком много памяти
У меня есть скрипт PHP, работающий с использованием инфраструктуры YII, который проходит через базу данных и создает лист Excel для экспорта. Количество данных в базе данных составляет около 15 тыс. Записей и увеличивается. Проблема в том, что скрипт потребляет много памяти, а размер файла Excel составляет около 45 МБ. Я могу попытаться сжать файл, чтобы сжать его до размера, который, я не думаю, будет проблемой, но сценарий, использующий больше памяти, - моя забота.
Один из способов решить эту проблему - обработать только 5 тыс. Записей за один раз, а затем добавить их все для создания файла Excel. Я не уверен, что так будет.
public function actionExport() {
Yii::import('ext.phpexcel.XPHPExcel');
XPHPExcel::init();
// Create new PHPExcel object
$objPHPExcel = new PHPExcel();
// Adding data
$objPHPExcel->setActiveSheetIndex(0)
->setCellValue('A1', 'SN')
->setCellValue('B1', 'Full Name')
->setCellValue('C1', 'Gender')
->setCellValue('D1', 'Date Of Birth')
->setCellValue('E1', 'Products')
$merchantModels = Merchant::model()->findAll();
$i = 2; //starting after the header row
foreach ($merchantModels as $model) {
$merchantPModels = MerchantProducts::model()->findAll(array(
'condition' => 'merchantID = :merchantID',
'params' => array(':merchantID' => $model->id),
));
$productStr= "";
$pStr ="";
$x = 0; // counter for the merchnat product Loop
foreach ($merchantModels as $MPmodel) {
if($MPmodel->product !== null){
$pStr = $MPmodel->product->productName;
}else{
$pStr = "";
}
if ($x == 0) { // First Object
$productStr = $pStr;
}else{
$productStr = $productStr . "," . $pStr;
}
$x++;
}
*
*/
$objPHPExcel->setActiveSheetIndex(0)
->setCellValue('A' . $i, $i - 1)
->setCellValue('B' . $i, $model->fullName)
->setCellValue('C' . $i, $model->gender)
->setCellValue('D' . $i, $model->dateOfBirth)
->setCellValue('E' . $i, $productStr);
$i++;
}
// Rename worksheet
$objPHPExcel->getActiveSheet()->setTitle('Merchants');
// Set active sheet index to the first sheet, so Excel opens this as the first sheet
$objPHPExcel->setActiveSheetIndex(0);
$date = new DateTime('NOW');
$date = $date->format('Y-m-d H:i:s'); // for example
$this->render('export', array(
'excelModel' => $objPHPExcel,
'date' => $date,
));
}
2 ответа
Вместо Merchant::model()->findAll()
Вы должны использовать CDbDataReader
, Вы потеряете удобство ActiveRecord, но он не будет загружать все записи в память, как вы это делали раньше.
Читатель данных возвращается из CDbCommand::query()
, Таким образом, вы можете сделать что-то вроде:
$command = Yii::app()->db->createCommand();
$merchants = $command->query('SELECT * FROM merchants');
foreach($merchants as $merchant) {
// Add to excel here
}
Я также работал над проектом по экспорту данных из MySQL, чтобы преуспеть. В моем сгенерированном листе XL у меня есть около 30 вкладок, и они представляют собой некоторые сложные формулы для разных ячеек. Я использую PHPExcel для этого. Но в моем случае я генерировал excel как работу cron, потому что это занимало много времени.
Здесь, если у вас есть какой-то сложный шаблон Excel, вы также можете сохранить созданный шаблон на сервере, а затем с помощью класса PHPExcel для чтения и записи вы можете прочитать этот шаблон, записать в него данные и сохранить его в новом файле.
Я думаю, что эта информация поможет вам. Пожалуйста, дайте мне знать, если вы хотите получить дополнительные разъяснения.