使用内爆时出现 CSV 错误
CSV error while using implode
请帮忙,我是 Yii 的新手。我想从 CGridView 中选中的行生成并导出 CSV 文件。当我使用静态 SQL 查询时它正常工作,但是当我在 WHERE
子句中使用 implode
函数时 - 控制器 returns 出错。
我调用控制器动作的按钮:
$this->widget('bootstrap.widgets.TbButtonGroup', array(
'type' => 'primary',
'size'=>'mini',
'buttons' => array(
array(
'label' => 'Export',
'type' => 'success',
'buttonType'=>'ajaxLink',
'encodeLabel'=>true,
'icon'=> 'th white',
'url'=>Yii::app()->createUrl('/propertyPurchaseSale/ExportChecked'),
'ajaxOptions'=>array(
"type" => "post",
"data" => "js:{ids:$.fn.yiiGridView.getSelection('property-purchase-sale-grid')}",
"update" => '#', 'success'=>"js:function(data) {window.location.assign('/propertyPurchaseSale/ExportChecked');}"),
array( //htmlOptions
)
),
array(
...
),
),
));
我的控制器操作:
public function actionExportchecked() {
header('Content-type: text/csv');
header('Content-type: multipart/form-data');
header('Content-Disposition: attachment; filename="Export_(' . date('H-i_d.m.Y') .').csv"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Description: File Transfer');
$fp = fopen('php://output', 'w');
if(Yii::app()->request->isAjaxRequest)
{
if(isset($_POST['ids']))
{
$idx = $_POST['ids'];
$count=Yii::app()->db->createCommand('SELECT COUNT(*) FROM property')->queryScalar();
// $sql='SELECT * FROM property WHERE id IN (981, 982, 985)'; --> when I use static values - all work
$sql="SELECT * FROM property WHERE id IN('".implode("', '",$idx)."')"; // --> when I use join or implode function - data exist in firebug, but page return error 500
$dataProvider=new CSqlDataProvider($sql, array(
'totalItemCount'=>$count,
'sort'=>array(
'attributes'=>array(
'fullname', 'address', 'phone', 'db_number', 'created_date'
),
),
'pagination'=>false,
));
fputs($fp, $bom =( chr(0xEF) . chr(0xBB) . chr(0xBF) ));
if ($fp)
{
echo PropertyPurchaseSale::model()->getAttributeLabel("id").";".
PropertyPurchaseSale::model()->getAttributeLabel("fullname").";".
PropertyPurchaseSale::model()->getAttributeLabel("address").";".
PropertyPurchaseSale::model()->getAttributeLabel("phone").";".
PropertyPurchaseSale::model()->getAttributeLabel("db_number").";".
PropertyPurchaseSale::model()->getAttributeLabel("created_date").
" \r\n";
foreach ($dataProvider->getData() as $data) {
echo $data['id'] . '; ' . $data['fullname'] . '; ' . $data['address'] . '; ' . $data['phone'] . '; ' . $data['db_number'] . '; ' . $data['created_date'] . '; ' . "\r\n";
}
}
exit;
}
}}
求助,我做错了什么?
我下意识的反应是没有任何东西可以证实 $_POST['ids']
是一个数组。如果它只是一个字符串,那么 implode 将失败,SQL 将被不正确地格式化,这将导致 500 级错误。
也许这可行:
// check for empty, that way invalid entry won't go through
if(!empty($_POST['ids'])) {
// Check if it is an array
$input_idx = is_array($_POST['ids'])?
// if so, then use it as an array
$_POST['ids']:
// If not, you need to turn it into an array. I'm only guessing that this should
// be a ','. It could be a " " or some other character(s)
explode(',',$_POST['ids']);
// Remove all non-numeric items in the array.
$idx = array_filter($input_idx, 'is_numeric');
if(!$idx) {
// Do something with bad data.
}
// continue with the line $count = ...
您还应该确保数据安全,因为这些 ID 可能包含 SQL 注入。 (Perhaps this answer)
请帮忙,我是 Yii 的新手。我想从 CGridView 中选中的行生成并导出 CSV 文件。当我使用静态 SQL 查询时它正常工作,但是当我在 WHERE
子句中使用 implode
函数时 - 控制器 returns 出错。
我调用控制器动作的按钮:
$this->widget('bootstrap.widgets.TbButtonGroup', array(
'type' => 'primary',
'size'=>'mini',
'buttons' => array(
array(
'label' => 'Export',
'type' => 'success',
'buttonType'=>'ajaxLink',
'encodeLabel'=>true,
'icon'=> 'th white',
'url'=>Yii::app()->createUrl('/propertyPurchaseSale/ExportChecked'),
'ajaxOptions'=>array(
"type" => "post",
"data" => "js:{ids:$.fn.yiiGridView.getSelection('property-purchase-sale-grid')}",
"update" => '#', 'success'=>"js:function(data) {window.location.assign('/propertyPurchaseSale/ExportChecked');}"),
array( //htmlOptions
)
),
array(
...
),
),
));
我的控制器操作:
public function actionExportchecked() {
header('Content-type: text/csv');
header('Content-type: multipart/form-data');
header('Content-Disposition: attachment; filename="Export_(' . date('H-i_d.m.Y') .').csv"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Description: File Transfer');
$fp = fopen('php://output', 'w');
if(Yii::app()->request->isAjaxRequest)
{
if(isset($_POST['ids']))
{
$idx = $_POST['ids'];
$count=Yii::app()->db->createCommand('SELECT COUNT(*) FROM property')->queryScalar();
// $sql='SELECT * FROM property WHERE id IN (981, 982, 985)'; --> when I use static values - all work
$sql="SELECT * FROM property WHERE id IN('".implode("', '",$idx)."')"; // --> when I use join or implode function - data exist in firebug, but page return error 500
$dataProvider=new CSqlDataProvider($sql, array(
'totalItemCount'=>$count,
'sort'=>array(
'attributes'=>array(
'fullname', 'address', 'phone', 'db_number', 'created_date'
),
),
'pagination'=>false,
));
fputs($fp, $bom =( chr(0xEF) . chr(0xBB) . chr(0xBF) ));
if ($fp)
{
echo PropertyPurchaseSale::model()->getAttributeLabel("id").";".
PropertyPurchaseSale::model()->getAttributeLabel("fullname").";".
PropertyPurchaseSale::model()->getAttributeLabel("address").";".
PropertyPurchaseSale::model()->getAttributeLabel("phone").";".
PropertyPurchaseSale::model()->getAttributeLabel("db_number").";".
PropertyPurchaseSale::model()->getAttributeLabel("created_date").
" \r\n";
foreach ($dataProvider->getData() as $data) {
echo $data['id'] . '; ' . $data['fullname'] . '; ' . $data['address'] . '; ' . $data['phone'] . '; ' . $data['db_number'] . '; ' . $data['created_date'] . '; ' . "\r\n";
}
}
exit;
}
}}
求助,我做错了什么?
我下意识的反应是没有任何东西可以证实 $_POST['ids']
是一个数组。如果它只是一个字符串,那么 implode 将失败,SQL 将被不正确地格式化,这将导致 500 级错误。
也许这可行:
// check for empty, that way invalid entry won't go through
if(!empty($_POST['ids'])) {
// Check if it is an array
$input_idx = is_array($_POST['ids'])?
// if so, then use it as an array
$_POST['ids']:
// If not, you need to turn it into an array. I'm only guessing that this should
// be a ','. It could be a " " or some other character(s)
explode(',',$_POST['ids']);
// Remove all non-numeric items in the array.
$idx = array_filter($input_idx, 'is_numeric');
if(!$idx) {
// Do something with bad data.
}
// continue with the line $count = ...
您还应该确保数据安全,因为这些 ID 可能包含 SQL 注入。 (Perhaps this answer)