如何使用Symfony将数据导出到CSV而不耗尽内存


How can I export data to a CSV using Symfony without running out of memory?

我遇到过几次这个问题。

我有一段将数据导出到 CSV 的代码。 我使用的方法将结果集传递给模板,模板循环浏览结果,回显字段。

在操作中:

$this->result = ObjectPeer::doSelect($criteria);

在模板中:

foreach ($result as $row)
{
  echo $row->getValue1().','.$row->getValue2().','.$row->getValue3()...
}

但是,如果结果集很大,我将耗尽内存:

 [error] PHP Fatal error:  Allowed memory size of 268435456 bytes exhausted (tried to allocate 1556481 bytes) in exportSuccess.php on line 13, referer: https://mysite.com/module

该进程使用超过 250 mb,但它创建的文件只有 ~2 mb。我可以增加 php.ini 为该过程提供的内存量,但我宁愿不这样做。 如果导出足够大,我有点怀疑我是否能够给它足够的内存。

我读过其他一些类似的案例,建议在每次回声后取消设置$row。 这在我的情况下不起作用。

我认为有一种方法可以对此查询进行分块并仍然构建整个文件 - 任何人都可以推荐或指出我一个清晰的教程吗?

根据要检索的元素数量(即:getValue1getValue2 等),您可以通过不同的方式对结果进行水化处理:

$stmt = ObjectPeer::doSelectStmt($m_criteria);
while ($row = $stmt->fetch(PDO::FETCH_NUM))
{
  echo $row[0];
}

此外,您可以使用doSelectRS检查另一个解决方案:

$rs = ObjectPeer::doSelectRS($criteria);
$rs->setFetchMode(ResultSet::FETCHMODE_ASSOC);
while($rs->next())
{
  $records = $rs->getRow();
  // then use $records['key'] to retrieve information
}

您可以检查的其他一些事情。这个关于记忆泄漏的法国人形成了普罗佩尔。

这是写入 csv 文件的基本思想。 这不会显示与数据库的连接,但它是之后的所有内容,并确保在最后关闭连接。

$filename = 'c:'whatever.csv';
$fp = fopen($filename, "w")  or die(mysql_error());
echo "Connected to ".$filename." <br>";

$res = mysql_query("SELECT *
FROM $table1 
WHERE Something
");
// fetch a row and write the column names out to the file
echo mysql_error();
$row = mysql_fetch_assoc($res);
$line = "";
$comma = "";
foreach($row as $name => $value) {
$line .= $comma . '"' . str_replace('"', '""', $name) . '"';
$comma = ",";
}
$line .= "'n";
fputs($fp, $line);
// remove the result pointer back to the start
mysql_data_seek($res, 0);
// and loop through the actual data
echo mysql_error();
while($row = mysql_fetch_assoc($res)) {
$line = "";
$comma = "";
foreach($row as $value) {
    $line .= $comma . '"' . str_replace('"', '""', $value) . '"';
    $comma = ",";
}
$line .= "'n";
fputs($fp, $line);
}