Yii 1.1: CSV Export

4 followers

I needed a csv export function for my cgridview and I wanted to export the entire result set of the sorted and filtered cgridview the user was viewing via ajax.

This reuses the search method so you don't have to rewrite any of your complex criteria or sort code.

I was not using ajaxupdate on the cgridview. IF you are then you need to change the view logic to send those params.

NOTE: Change "searchRailcars" and "TrainCars" for your respective page name and model

View

list($url, $getParams) =   explode("searchRailcars", $_SERVER["REQUEST_URI"]); //will split the url to return all the get params aftert the r param
<a href="<?php echo url('/rip/search/csvRailcars'.$getParams); ?>">CSV Export</a>

MODEL

public function search($pagination = array( 'pageSize'=>20) ){ //edited to set pagination
...
//the criteria and sort logic
...
          return new CActiveDataProvider($this, array('criteria' => $criteria,
                                                      'sort'=>$sort,
                                                      'pagination'=>$pagination
                                        ));
 
} //end func

CONTROLLER

public function actionCsvRailcars(){       
         header('Content-type: text/csv');
         header('Content-Disposition: attachment; filename="centrico-RIP-Railcars-' . date('YmdHi') .'.csv"');
 
         $model=new TrainCars('search');
         $model->unsetAttributes();  // clear any default values
         if(isset($_GET['TrainCars'])) $model->attributes=$_GET['TrainCars'];
         $dataProvider = $model->search(false);
 
         //csv header
         echo TrainCars::model()->getAttributeLabel("beginTime_n").",". TrainCars::model()->getAttributeLabel("endTime_n").",". TrainCars::model()->getAttributeLabel("sequence_n")." \r\n";
 
          foreach ($dataProvider->getData() as $data)
           echo "$data->beginTime_n,$data->endTime_n, $data->sequence_n \r\n";
         }
         exit;      
}

Total 5 comments

#8665 report it
marcovtwout at 2012/06/18 06:01am
Extensions available

You can also use one of the yii-extensions, like this one: http://www.yiiframework.com/extension/csvexport

#8595 report it
JohnPollard at 2012/06/13 01:31pm
RE:Suggestions

XSS: I'm still unsure how what I am doing is any different than what yii does by default with the cgridview not using ajax.

Page Parameter: I agree Ill edit it to change to that. I read through the forums and someone said you couldnt get the entire result set back, you had to use cactiverecord.

#8594 report it
François Gannaz at 2012/06/13 01:05pm
Re: Suggestions
  • XSS: It's still there and could lead to session hijacking or similar treats. Here is a link about XSS: OWASP, and shamelessly my own wiki page.
    See what would happen if someone puts a link (or an image's src) toward your page with an URL like ...&hack="><script>....</script>.
    Fixing this isn't obvious as you can't simply escape the URL part. In another wiki page, someone used JS for this. Another way would be to add a form with submit buttons wrapping the CGridView. You could also use a mix of CController::createUrl() and $model->attributes to create a static link.

  • $page parameter: sorry, my bad. I thought it was part of the official template, but it's only in my custom one. I still dislike the way your method returns results of different types depending on the $all param. Why don't you use a CActiveDataProvider with the config 'pagination' => false?

  • Validation: you're using non-validated user input to build your criteria in the line $dataProvider = $model->search(true);. This is dangerous. BTW, as I wrote above, $dataProvider is an array in this case, not an instance of CDataProvider, and I think this is very confusing.

#8592 report it
JohnPollard at 2012/06/13 11:57am
Re: Suggestions
  • I edited the indentation. Lemme know if you still don't like something.
  • Is this any different than how the page normally gets updated when cgridview has ajaxUpdate = false?
  • $page parameter? All my models are generated from gii and don't have that param.
  • Again, I don't see that parameter.
  • I agree. Just thought this way was simpler.
  • Does this differ from point #2 and #4?

I appreciate your suggestions.

#8590 report it
François Gannaz at 2012/06/13 08:56am
Suggestions

Here are several suggestions on potential enhancements of this wiki page:

  • Please fix the indentation.
  • There's an XSS flaw in the view, at the beginning of the page.
  • Depending on the $page parameter, TrainCars::search() will return a CDataProvider or an array(). This is inconsistent and may lead to errors.
  • The model should keep the default method search($page=25) with no pagination when the parameter $page is false.
  • To output CSV, one shouldn't use a naive echo but the official PHP function fputcsv. Without this it would break on content like « "my,punctuation;" ».
  • When the controller puts user input into the model, it must validate it (security concern) and output CSV only if this doesn't fail.

Sorry if I sound negative. If you feel like it, I'd be glad to provide explanations on any point I mentioned.

Leave a comment

Please to leave your comment.

Write new article
  • Written by: JohnPollard
  • Category: How-tos
  • Yii Version: 1.1
  • Votes: +4
  • Viewed: 12,040 times
  • Created on: Jun 12, 2012
  • Last updated: Jun 13, 2012
  • Tags: csv, export