所以我有这段代码:
$list = $this->user_model->get_users($prefKey, $searchKey, $withEmail, "", "");
$headerArray = array("id", "prefecture_id", "industry");
$header = str_replace(",", "", $headerArray);
$datas = implode(',', $header) . "\r\n";
foreach($list as $body)
{
$orig_email = $body['email'];
$mstring = preg_replace("/^([^a-zA-Z0-9])*/",',',$orig_email);
preg_match_all("/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i", $mstring, $matches);
$email = implode($matches[0]);
$datas .= $body["id"].",".$body["prefecture_id"].",".$body["industry_id"].",".$email."\r\n";
$datas = '"' . implode('","', $body).'"';
}
$datas = mb_convert_encoding($datas, "SJIS-win", "UTF-8");
$csvFileName = "phpList_" . date('Ymd_His') . ".csv";
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $csvFileName);
header('Content-Transfer-Encoding: binary');
while (ob_get_level() > 0)
{
ob_end_clean();
}
ob_start();
print trim($datas);
ob_flush();
ob_end_clean();
exit;
它只是这样:
"3","Tesla","Cars","admin@volvo.com"
我想要的是这样的:
"1","Volvo","Cars","admin@volvo.com"
"2","Honda","Cars","admin@honda.com"
"3","Tesla","Cars","admin@tesla.com"
当我调用此函数时,它只给出csv下载文件,只有1个数据(最终数据)。如何遍历所有数据?
答案 0 :(得分:3)
你是说你只获得了csv中加载的最后一条记录吗?
使用此行替换当前$datas
中的所有数据:
$datas = '"' . implode('","', $body).'"';
这样,只有循环的最后一次迭代的最后一行最终对最终结果有用。不确定这是不是问题,但也许
$datas .= '"' . implode('","', $body).'"';
P.S。我不确定您是否要保留foreach
P.p.s。您可能希望在csv中添加一些行结尾。
答案 1 :(得分:2)
您的变量被覆盖
foreach($list as $body){
....
$datas .= $body["id"].",".$body["prefecture_id"].",".$body["industry_id"].",".$email."\r\n";
$datas = '"' . implode('","', $body).'"'; //overwritten by body
}
这两条线对它们的方式毫无意义。每次迭代你+ =连接$datas
,然后你立即用其他数据覆盖它。
例如,在第一次迭代时它是
$datas = implode(',', $header) . "\r\n";
$datas .= $body["id"].",".$body["prefecture_id"].",".$body["industry_id"].",".$email."\r\n";
$datas = '"' . implode('","', $body).'"'; //over written
下一次迭代是前一次(上面的最后一行)
$datas = '"' . implode('","', $body).'"';
然后
$datas .= $body["id"].",".$body["prefecture_id"].",".$body["industry_id"].",".$email."\r\n";
$datas = '"' . implode('","', $body).'"'; //over written
看看我的意思是没有意义的。
使这有意义的唯一方法是做这样的事情
$datas = [implode(',', $header)];
foreach($list as $body)
{
$orig_email = $body['email'];
$mstring = preg_replace("/^([^a-zA-Z0-9])*/",',',$orig_email);
preg_match_all("/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i", $mstring, $matches);
$email = implode($matches[0]);
$datas[] = [
$body["id"],
$body["prefecture_id"],
$body["industry_id"],
$email
];
}
$datas = imploade(PHP_EOL, $datas);
但即使这不是制作csv文件的正确方法,您应该使用fputcsv
。如果"
中的$body
您的CSV将被废弃,会发生什么。
更新和解决方案
这就是我编码的方式,但我不知道你为什么要更改编码:
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $csvFileName);
header('Content-Transfer-Encoding: binary');
//open the output stream, this acts like a file but just outputs the contents.
$f = fopen('php://output', 'w');
fputcsv($f, $header);
//create a mapping array for the headers ( if the order is different then $body )
$default = array_fill_keys( $headers, '');
/*
assuming headers is like this
['id', 'prefecture_id', 'industry_id', 'email']
this will create a "mapping" array like this
['id'=>'', 'prefecture_id'=>'', 'industry_id'=>'', 'email'=>'']
*/
foreach($list as $body)
{
$orig_email = $body['email'];
$mstring = preg_replace("/^([^a-zA-Z0-9])*/",',',$orig_email);
if( preg_match_all("/[\._a-zA-Z0-9-]+@[\._a-zA-Z0-9-]+/i", $mstring, $matches)){
$body['email'] = implode($matches[0]);
}else{
//prevent undefined offset warning in $matches when there are none.
$body['email'] = '';
}
/*
merge $body with the mapping array
if the keys match the '' in $default will be replaced by the
value in $body for the same key.
----------------------------------------
assuming data like this '$body'
['email' => 'mail@example.com', 'industry_id'=>321,'id'=>1, 'prefecture_id' => 123]
and our mapping like this '$default'
['id'=>'', 'prefecture_id'=>'', 'industry_id'=>'', 'email'=>'']
this will change $body to
['id'=>1, 'prefecture_id'=>123, 'industry_id'=>321, 'email'=>'mail@example.com']
*/
$body = array_replace($default, $body);
//after mapping it $body will match $header order and lenght
//so we just send it to the output stream buffer.
fputcsv($f, $body);
//flush the output buffer to the browser.
flush();
}
供参考(关于如何将数据映射到标题)
array_fill_keys()使用keys数组的值作为键,使用value参数的值填充数组。
http://php.net/manual/en/function.array-fill-keys.php
array_replace()将array1的值替换为以下每个数组中具有相同键的值。如果第一个数组中的键存在于第二个数组中,则其值将替换为第二个数组中的值。