Created
September 4, 2017 19:53
-
-
Save ogero/785c8cfab343575aedf57d89d0efe86d to your computer and use it in GitHub Desktop.
Export grid to csv
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* GridView Export Behavior | |
* Requirements: | |
* Yii 1.1.3 or greater | |
* An explicit rule on the action that exports the csv like: '<controller:\w+>/<action:\w+>' => '<controller>/<action>' | |
* Usage: | |
* <pre> | |
* //(Step 1) Add this behavior to the controller like | |
public function behaviors() { | |
return array( | |
'exportableGrid' => array( | |
'class' => 'application.components.ExportableGridBehavior', | |
)); | |
} | |
* //(Step 2) On actionAdmin() , add this line before render('admin') method | |
if ($this->isExportRequest()) { | |
$this->exportCSV(array('EXPORT DATE ',date('Y-m-d')), null, false); | |
$this->exportCSV($model, array_keys($model->attributeLabels()), false, 3); | |
$this->exportCSV($model->search(), array('id', 'comment', 'date:date', 'published:boolean:Comment approved', 'user.name', 'user.id')); | |
} | |
* //(Step 3) On the view that renders the grid, link some DOM element to the export action | |
$this->registerExportGridScript(); | |
* //Then on any element add onClick="exportGrid('#gridId')" | |
* //Optionally add your own params to the export action like onClick="exportGrid('#gridId','myUrlEncodedKey=myUrlEncodedValue')" | |
* // (Optional) If you need to export a very large dataset, you need to add this before exportCSV() | |
set_time_limit(0); | |
* </pre> | |
* @version 2.2 | |
* @author Geronimo Oñativia / https://pixdart.com | |
* @link http://www.yiiframework.com/extension/exportablegridbehavior | |
*/ | |
class ExportableGridBehavior extends CBehavior { | |
public $exportParam = 'export'; //Param to be appended on url to fire an export | |
public $csvDelimiter = ','; //Columns delimiter | |
public $csvEnclosure = '"'; //Enclosure used on data when needed | |
public $filename = 'export.csv'; //Filename suggested to user when downloading | |
public $addUTF8BOM = true; //Adds \xEF\xBB\xBF to output | |
private $headersSent = false; | |
private $_formatter = null; | |
/** | |
* @return CFormatter the formatter instance. Defaults to the 'format' application component. | |
*/ | |
protected function getFormatter() { | |
if ($this->_formatter === null) | |
$this->_formatter = Yii::app()->format; | |
return $this->_formatter; | |
} | |
/** | |
* Fetch from an array of strings, the column name, type and header | |
* @param type $columns ['enabled:boolean:LoginEnabled',] | |
* @return array array ie [[name=>enabled,type=>boolean,header=>LoginEnabled],] | |
*/ | |
protected function createColumnsArray($columns) { | |
$columnsArray = []; | |
if (is_array($columns)) { | |
foreach ($columns as $text) { | |
if (!preg_match('/^([\w\.]+)(:(\w*))?(:(.*))?$/', $text, $matches)) | |
throw new CException(Yii::t('zii', 'The attributes must be specified in the format of "Name:Type:Label", where "Type" and "Label" are optional.')); | |
$column = ['name' => $matches[1], 'type' => 'raw']; | |
if (isset($matches[3]) && $matches[3] !== '') | |
$column['type'] = $matches[3]; | |
if (isset($matches[5])) | |
$column['header'] = $matches[5]; | |
$columnsArray[] = $column; | |
} | |
} | |
return $columnsArray; | |
} | |
/** | |
* @param mixed $data A Traversable of CModel or a CModel where data will be fetch from | |
* @param array $columns Attribute names of CModel to be exported. | |
* @param bool $endApplication Application will be ended if true. false to keep going and export more data. Defautls to TRUE. | |
* @param integer $endLineCount Number of newlines to append below this data. Defaults to 0. | |
*/ | |
public function exportCSV($data, $columns = null, $endApplication = true, $endLineCount = 0) { | |
$this->sendHeaders(); | |
$fileHandle = fopen('php://output', 'w'); | |
$columnsArray = $this->createColumnsArray($columns); | |
if ($data instanceof CActiveDataProvider) { | |
$this->csvRowHeaders($fileHandle, $columnsArray, $data->model); | |
$this->csvRowModels($fileHandle, new CDataProviderIterator($data, 150), $columnsArray); | |
} else if (is_array($data) && current($data) instanceof CModel) { | |
$this->csvRowHeaders($fileHandle, $columnsArray, current($data)); | |
$this->csvRowModels($fileHandle, $data, $columnsArray); | |
} else if (is_array($data) && is_string(current($data))) { | |
fputcsv($fileHandle, $data, $this->csvDelimiter, $this->csvEnclosure); | |
} else if ($data instanceof CModel) { | |
$this->csvModel($fileHandle, $data, $columnsArray); | |
} | |
fprintf($fileHandle, str_repeat("\n", $endLineCount)); | |
fclose($fileHandle); | |
if ($endApplication) { | |
Yii::app()->end(0, false); | |
exit(0); | |
} | |
} | |
private function csvRowHeaders($fileHandle, $columnsArray, CModel $model) { | |
$row = []; | |
foreach ($columnsArray as $column) { | |
$row[] = (isset($column['header']) ? $column['header'] : $model->getAttributeLabel($column['name'])); | |
} | |
fputcsv($fileHandle, $row, $this->csvDelimiter, $this->csvEnclosure); | |
} | |
private function csvRowModels($fileHandle, Traversable $cModels, $columnsArray) { | |
foreach ($cModels as $cModel) { | |
$row = []; | |
foreach ($columnsArray as $column) { | |
$value = CHtml::value($cModel, $column['name']); | |
$row[] = ($value == null ? '' : $this->getFormatter()->format($value, $column['type'])); | |
} | |
fputcsv($fileHandle, $row, $this->csvDelimiter, $this->csvEnclosure); | |
} | |
} | |
private function csvModel($fileHandle, CModel $cModel, $columnsArray) { | |
foreach ($columnsArray as $column) { | |
$row = []; | |
$row[] = (isset($column['header']) ? $column['header'] : $cModel->getAttributeLabel($column['name'])); | |
$value = CHtml::value($cModel, $column['name']); | |
$row[] = ($value == null ? '' : $this->getFormatter()->format($value, $column['type'])); | |
fputcsv($fileHandle, $row, $this->csvDelimiter, $this->csvEnclosure); | |
} | |
} | |
private function sendHeaders() { | |
if ($this->headersSent === false) { | |
$this->headersSent = true; | |
// disable caching | |
$now = gmdate("D, d M Y H:i:s"); | |
header("Expires: Tue, 01 Jan 2013 00:00:00 GMT"); | |
header("Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate"); | |
header("Last-Modified: {$now} GMT"); | |
// force download | |
header("Content-Type: application/force-download"); | |
header("Content-Type: application/octet-stream"); | |
header("Content-Type: application/download"); | |
// disposition / encoding on response body | |
header("Content-Disposition: attachment;filename=\"{$this->filename}\""); | |
header("Content-Transfer-Encoding: binary"); | |
if ($this->addUTF8BOM) | |
print "\xEF\xBB\xBF"; | |
} | |
} | |
public function isExportRequest() { | |
return Yii::app()->request->getParam($this->exportParam, false); | |
} | |
/** | |
* Registers the export script | |
* To export a grid call function js:exportGrid('#myGrid') | |
* Optionally add an extra parameter like js:exportGrid('#myGrid','myUrlEncodedKey=myUrlEncodedValue') | |
*/ | |
public function registerExportGridScript() { | |
Yii::app()->clientScript->registerScript('ExportableGridBehaviorScript', <<<SCRIPT | |
function exportGrid(gridSelector,extraParam) { | |
extraParam = typeof extraParam !== 'undefined' ? '&'+extraParam : ''; | |
var downloadUrl=$(gridSelector).yiiGridView('getUrl'); | |
downloadUrl+=((downloadUrl.indexOf('?')==-1)?'?':'&'); | |
downloadUrl+='{$this->exportParam}=1'; | |
downloadUrl+=extraParam; | |
window.open( downloadUrl ,'_blank'); | |
} | |
SCRIPT | |
, CClientScript::POS_END); | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment