【问题标题】:Simple HTML DOM Memory issue简单的 HTML DOM 内存问题
【发布时间】:2015-06-25 15:28:21
【问题描述】:

我正在尝试使用 PHP Simple HTML Dom Parser 从 SQL 查询结果中解析一些信息。但它似乎存在一些巨大的内存问题。我使用 SQL 查询结果创建了一个 html 表,然后将 html 表导出到一个 csv 文件。我对此真的很陌生,所以我的代码不是最有效的。当我的查询结果很小时,会成功创建 csv 文件。但是当查询结果很大时,导出的csv文件没有任何sql结果,而是显示如下:

致命错误:在第 101 行的 /opt/lampp/htdocs/test.php 中的布尔值上调用成员函数 find()

这是我的函数,它获取 sqlresult 并创建一个 html 表,然后将其导出到一个 csv 文件中:

 echo sql_to_html_table($sqlresult, $delim="\n" );

function sql_to_html_table($sqlresult, $delim="\n") {
// starting table
include_once('simple_html_dom.php');
$htmltable =  "<table>" . $delim ;
$counter   = 0 ;
// putting in lines
//while( $row = $sqlresult->mysqli_fetch_assoc()  ){
while($row = mysqli_fetch_assoc($sqlresult)) {
if ( $counter===0 ) {
// table header
$htmltable .=   "<tr>"  . $delim;
foreach ($row as $key => $value ) {
      $htmltable .=   "<th>" . $key . "</th>"  . $delim ;
  }
  $htmltable .=   "</tr>"  . $delim ;
  $counter = 22;
 }
  // table body
  $htmltable .=   "<tr>"  . $delim ;
  foreach ($row as $key => $value ) {
      $htmltable .=   "<td>" . $value . "</td>"  . $delim ;
  }
  $htmltable .=   "</tr>"   . $delim ;
 }
 // closing table

$htmltable .=   "</table>"   . $delim ;
 // return
//return( $htmltable ) ;
$html = str_get_html($htmltable);

header('Content-type: application/ms-excel');
header('Content-Disposition: attachment; filename=sample.csv');

$fp = fopen("php://output", "w");

foreach($html->find('tr') as $element)
{
$td = array();
foreach( $element->find('th') as $row)
{
    $td [] = $row->plaintext;
}
fputcsv($fp, $td);
$td = array();
foreach( $element->find('td') as $row)
{
    $td [] = $row->plaintext;
}
fputcsv($fp, $td);
}
fclose($fp);
} 

我尝试在 $html = str_get_html($htmltable); 之后抛出异常像这样:

if (!str_get_html($htmltable)) {
throw new exception('exception') ; 
}

当我尝试运行代码时,我的浏览器给了我这个错误:

致命错误:/opt/lampp/htdocs/test.php:96 中未捕获的异常 'Exception' 和消息 'exception' 堆栈跟踪:#0 /opt/lampp/htdocs/test.php(62): sql_to_html_table( Object(mysqli_result), '\n') #1 {main} 在第 96 行的 /opt/lampp/htdocs/test.php 中抛出

【问题讨论】:

  • 你为什么要从 sql 到 html 到 csv?为什么不用mysql自带的csv导出功能呢?
  • 我基本上是在使用 php 开发前端。所以我需要从下拉菜单中选择一个 SQL 查询,然后单击一个按钮来生成并保存 csv 文件。我知道如何使用 csv 导出功能来保存文件,但我的老板想使用弹出窗口保存它。
  • 好吧,您的错误并不表示存在任何内存问题。它说您正在尝试在第 101 行的布尔值上调用函数 find()。我假设这是这一行: foreach($html->find('tr') as $element) 如果是的话 $html 包含什么,我会 print_r($html);查找内容以查看它是字符串还是布尔值并从那里开始
  • 但是我之前提到过,当我运行一个结果中有几行的 SQL 脚本时,它工作得非常好。仅当我使用结果中包含大量行的 sql 脚本时才会出现此问题。你还觉得没有内存问题吗?
  • 我一直在说没有发布内存错误。大多数 DOM 加载器会将行一一加载到内存中。我们在谈论多少个结果?你得到什么内存错误?

标签: php html mysql csv simple-html-dom


【解决方案1】:

查看来自 SourceForge 的 simple_html_dom.php 副本,这听起来像是对于足够大的 HTML 字符串的预期行为。我看到 str_get_html() 有一个检查,如果字符串的大小大于 MAX_FILE_SIZE,它将导致它返回 false。并且 MAX_FILE_SIZE 定义为:

define('MAX_FILE_SIZE', 600000);

所以看起来 simple_html_dom 不会处理任何大于大约 600kb 的字符串。由于这是一个内置限制,我想您的选择是尝试更改限制并查看会发生什么或使用不同的库。

或者,您可以完全跳过 HTML 部分。如果您需要为其他目的生成 HTML,那很好,但是您没有理由不能通过直接从数据库结果而不是 HTML 构建 CSV 来绕过这个问题。

【讨论】:

  • 我对此很陌生,我不知道如何直接从数据库而不是 HTML 中获取 CSV 结果。你能帮我一下吗?
  • 好吧,只需使用您已有的内容来构建 HTML。现在,您正在从 MySQL 获取数据,将其转换为 HTML,并将 HTML 转换为 CSV。这是相同的数据,因此当您循环访问它们时,没有理由不能直接对数据库结果执行 fputcsv()。生成 CSV 完全不需要 HTML。
【解决方案2】:

也许这更容易理解:

function sql_to_csv($sqlresult, $delim = "\n") {

    // Loop each result into a csv row string
    while($row = mysqli_fetch_assoc($sqlresult)) {

        // Create/reset a var to hold the csv row content
        $csvRow = '';

        // Append each column value comma separated
        // Be warned of column values containing commas
        foreach ($row AS $columnValue) {
            $csvRow .= $columnValue . ',';
        }

        // Remove the trailing comma from the final column
        rtrim($csvRow, ',');

        // Send your CSV row to the browser
        echo $csvRow . $delim;
    }

    header('Content-type: text/csv');
    header('Content-Disposition: attachment; filename=sample.csv');
}

这种方法存在各种问题,不仅限于大输出缓冲区、带有多逗号的列...等我认识到这些问题,但希望提供一种早期解决方案而不是一大块文本。

调试 PHP 代码最简单的方法是使用 de-bugg 输出来运行它,如果上面没有用,以下内容可能会对您有所帮助:

var_dump($variable);
exit;

这将使您能够在运行时查看变量的内容,并且可以更好地指示您的异常,给定异常中的行号。

祝你好运。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多