我正在为客户开发一个项目 - 一个用于创建和维护组织成员数据库的 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
建立的,然后将每一行格式化为逗号分隔和 fwrite
d,最后文件被 fclose
d 推送到本地系统。
我(从服务器)收到的错误是
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 诊断之后),因此至少可以正常工作。
我猜测有一些东西阻止了 fopen
、fwrite
或 fclose
函数正常工作(服务器设置?),但是我没有足够的经验来确定问题所在。
我会再次注意到,这在我的测试环境(localhost/XAMPP、netbeans)中完全按照预期工作。
如有任何想法,我们将不胜感激。
更新
好的 - 今天又花了一些时间来解决这个问题。我已尝试了每个建议的修复,包括 @Rudu 的 writeCSVLine
修复和 @Fernando Costa 的 file_put_contents()
建议。事实是,他们都在本地工作。无论是 echo
ing 还是 fopen
、fwrite
、fclose
例程,都没关系,效果很好。
问题似乎在于文件开头包含 wp-blog-header.php
,然后是额外的 header()
调用。 (顺便说一句,该路径在服务器上绝对是正确的。)
如果我注释掉 include
,我会下载一个 csv 文件,其中包含一些错误(因为 $wpdb
不存在。如果注释掉header
s,我将所有数据打印到页面上。
那么...你知道这里会发生什么吗?
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/