我正在为客户开发一个项目 - 一个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 modify header information
(我很确定,因为phpinfo()
已经生成了头)。然而,所有预期的数据都会打印到页面底部(在所有phpinfo诊断之后),因此至少可以正常工作。
我猜有些东西阻止fopen
,fwrite
或fclose
功能正常工作(服务器设置?),但我没有足够的经验准确地确定问题所在。
我会再次注意到,这在我的测试环境中完全符合预期(localhost / XAMPP,netbeans)。
任何想法都会非常感激。
好的 - 今天花了一些时间。我已经尝试了每个建议的修复程序,包括@ Rudu的writeCSVLine
修正和@Fernando Costa的file_put_contents()
建议。事实是,它们都在本地工作。只是echo
或fopen
,fwrite
,fclose
例程无关紧要,效果很好。
似乎有问题的是在文件的开头包含wp-blog-header.php
,然后是其他header()
次调用。 (路径在服务器上肯定是正确的,顺便说一句。)
如果我注释掉include
,我会下载一个csv文件,其中包含一些错误(因为$wpdb
不存在。如果注释掉header
,我将所有数据打印到页面上。
那么......任何想法可能会在这里发生什么? wordpress环境的一些明显冲突和文件的正确创建。
学习很多,但没有接近答案......想想我可能只需要避免wordpress的东西并做一个手动的SQL查询。
答案 0 :(得分:1)
好的,所以我想知道为什么你采取这种方法。 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
。
答案 1 :(得分:1)
进入同样的问题。偶然发现这个线程执行相同的操作,但挂钩到'plugins_loaded'操作并导出CSV然后。 https://wordpress.stackexchange.com/questions/3480/how-can-i-force-a-file-download-in-the-wordpress-backend
提前导出CSV消除了在您到达之前已经修改标头的风险。