php - CSV 文件生成错误

标签 php mysql wordpress csv

我正在为客户开发一个项目 - 一个用于创建和维护组织成员数据库的 WordPress 插件。我会注意到这个插件在 WordPress 数据库中创建一个新表(而不是将数据作为 custom_post_type 元数据处理)。我对插件的大部分内容进行了很多修改,但我遇到了一个功能问题(我没有更改)。

此功能的一半执行 csv 导入和插入,效果非常好。该序列的另一半是将该表的内容下载为 csv 的功能。这部分在我的本地系统上工作正常,但从服务器运行时失败。我仔细研究了这个脚本的每一部分,一切似乎都有意义。坦率地说,我不知道为什么会失败。

包含逻辑的 php 文件被简单地链接到。文件:

<?php
    // initiate wordpress
    include('../../../wp-blog-header.php');

    // phpinfo();    

    function fputcsv4($fh, $arr) {
        $csv = "";
        while (list($key, $val) = each($arr)) {
            $val = str_replace('"', '""', $val);
            $csv .= '"'.$val.'",';
        }
        $csv = substr($csv, 0, -1);
        $csv .= "\n";
        if (!@fwrite($fh, $csv)) 
            return FALSE;
    }

    //get member info and column data
    $table_name = $wpdb->prefix . "member_db";
    $year = date ('Y');
    $members = $wpdb->get_results("SELECT * FROM ".$table_name, ARRAY_A);
    $columns = $wpdb->get_results("SHOW COLUMNS FROM ".$table_name, ARRAY_A);
    // echo 'SQL: '.$sql.', RESULT: '.$result.'<br>';

    //output headers
    header("Content-type: application/octet-stream");
    header("Content-Disposition: attachment; filename=\"members.csv\"");

    //open output stream
    $output = fopen("php://output",'w'); 

    //output column headings
    $data[0] = "ID";
    $i = 1;
    foreach ($columns as $column){
        //DIAG: echo '<pre>'; print_r($column); echo '</pre>';
        $field_name = '';
        $words = explode("_", $column['Field']);
        foreach ($words as $word) $field_name .= $word.' ';
        if ( $column['Field'] != 'id' && $column['Field'] != 'date_updated' ) {
            $data[$i] = ucwords($field_name);
            $i++;
        }
    }
    $data[$i] = "Date Updated";
    fputcsv4($output, $data);

    //output data
    foreach ($members as $member){
        // echo '<pre>'; print_r($member); echo '</pre>';
        $data[0] = $member['id'];
        $i = 1;
        foreach ($columns as $column){
            //DIAG: echo '<pre>'; print_r($column); echo '</pre>';
            if ( $column['Field'] != 'id' && $column['Field'] != 'date_updated' ) {
                $data[$i] = $member[$column['Field']];
                $i++;
            }
        }
        $data[$i] = $member['date_updated'];
        //echo '<pre>'; print_r($data); echo '</pre>';
        fputcsv4($output, $data); 
    }
    fclose($output);
?>

因此,显然,运行查询的例程,$output 是使用 fopen 建立的,然后将每一行格式化为逗号分隔和 fwrited,最后文件被 fclosed 推送到本地系统。

我(从服务器)收到的错误是

Error 6 (net::ERR_FILE_NOT_FOUND): The file or directory could not be found.

但它显然正在被发现,它只是失败了。如果我在文件顶部启用 phpinfo() (PHP 版本 5.2.17),我肯定会得到一个响应 - 特别是 Cannot edit header information (我很漂亮当然,因为 phpinfo() 已经生成了一个 header )。然而,所有预期的数据都会打印到页面底部(在所有 phpinfo 诊断之后),因此至少可以正常工作。

我猜测有一些东西阻止了 fopenfwritefclose 函数正常工作(服务器设置?),但是我没有足够的经验来确定问题所在。

我会再次注意到,这在我的测试环境(localhost/XAMPP、netbeans)中完全按照预期工作。

如有任何想法,我们将不胜感激。

更新

好的 - 今天又花了一些时间来解决这个问题。我已尝试了每个建议的修复,包括 @Rudu 的 writeCSVLine 修复和 @Fernando Costa 的 file_put_contents() 建议。事实是,他们都在本地工作。无论是 echoing 还是 fopenfwritefclose 例程,都没关系,效果很好。

问题似乎在于文件开头包含 wp-blog-header.php ,然后是额外的 header() 调用。 (顺便说一句,该路径在服务器上绝对是正确的。)

如果我注释掉 include,我会下载一个 csv 文件,其中包含一些错误(因为 $wpdb 不存在。如果注释掉headers,我将所有数据打印到页面上。

那么...你知道这里会发生什么吗?
wordpress 环境和文件的正确创建存在一些明显的冲突。

学到了很多东西,但还没有接近答案...我想我可能需要避免使用 wordpress 的东西并进行手动 sql 查询。

最佳答案

好的,我想知道您为什么采取这种方法。 php://output 没有任何问题但它所做的只是允许您以与 print 和 echo 相同的方式写入输出缓冲区...如果您遇到问题有了它,只需使用 print 或 echo :) 通过在流上使用 fwrite 获得的任何优化都会因字符串构建 $csv 变量而丢失,然后将其一次性写入输出流(并不是特别需要优化)。考虑到我的解决方案(与您最初的设计保持一致)将是这样的:

function escapeCSVcell($val) {
    return str_replace('"','""',$val);
    //What about new lines in values?  Perhaps not relevant to your
    // data but they'll mess up your output ;)
}
function writeCSVLine($arr) {
    $first=true;
    foreach ($arr as $v) {
        if (!$first) {echo ",";}
        $first=false;
        echo "\"".escapeCSVcell($v)."\"";
    }
    echo "\n"; // May want to use \r\n depending on consuming script
}

现在使用 writeCSVLine 代替 fputcsv4

关于php - CSV 文件生成错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6846405/

相关文章:

javascript - 如何使用 Ajax .serialize() 数据将表单发布到 PHP?

mysql - 加入两个 mysql 查询并包含计数为零的列值

python - 如何进行重复 key 更新

php - 在 PHP 中处理两个 mysql 连接

php - Zend PHP 认证样题

MySQL LIMIT 使用 SELECT COUNT(*) 作为 SELECT 中的值

javascript - 从 Wordpress REST API 获取所有对象的列表

javascript - 如何在WordPress帖子中仅显示月份和年份

php - 如何优化php进程内存占用?

php - json_encode 数组的特定部分