I needed to add Excel capability to some of my reports in Recess! so I decided a plugin would be the best way to go. There isn’t too much documentation on plugins so far, so I hope this can help a little. This may not be the best way to go, but it can at least be a guide to get started. I chose PHPExcel to be the engine I use to generate the Excel files. Its easy to generate several different versions of files, and csv and pdf, and I like the library.
The entire plugin is downloaded here.
The Recess! way to do this is create a View that Recess can use to display data. The views are called from the controller, so I want to use the view as follows:
| PHP | | copy code | | ? |
| 1 | /* |
| 2 | * !RespondsWith Layouts, ExcelView |
| 3 | */ |
The first thing I had to do was create the plugin directory structure and copy the PHPExcel files in. I copied the PHPExcel Classes/ directory into plugins/ryanday/PHPExcel/. Because the Library::import() method assumes FILE.class.php, I had to link PHPExcel.class.php to the actual PHPExcel.php file for things to function smoothly. There may be a way around that, but I figure its part of Recess!izing the library. This is probably a little confusing, so this is what the directory looks like:
- Classes/
- ExcelView.class.php
- PHPExcelPlugin.class.php
- Classes/
- PHPExcel/
- PHPExcel.class.php -> PHPExcel.php
- PHPExcel.php
Please download a copy of the plugin to make it a little more clear.
I started by viewing thebeeline’s post about plugins to get a jumping off point. Then I created the plugin file, PHPExcelPlugin.class.php
| PHP | | copy code | | ? |
| 01 | <?php |
| 02 | Library::import('recess.framework.Plugin'); |
| 03 | Library::import('ryanday.PHPExcel.Classes.PHPExcel'); |
| 04 | Library::import('ryanday.PHPExcel.ExcelView'); // This will let us create our own view |
| 05 | |
| 06 | class PHPExcelPlugin extends Plugin { |
| 07 | |
| 08 | function init(Application $app) { |
| 09 | MimeTypes::register('xls','application/vnd.ms-excel'); |
| 10 | } |
| 11 | |
| 12 | }; |
| 13 |
In the init() function I register a new MimeType, ‘xls’. When Recess! can’t find a layout to display data, it will pass registered mimetypes to all the views, so we have to register the ‘xls’ mimetype so our plugin can respond. Recess! will automatically create the headers for xls, and the applications type. Next we create the actual view.
| PHP | | copy code | | ? |
| 01 | <?php |
| 02 | Library::import('recess.framework.AbstractView'); |
| 03 | |
| 04 | class ExcelView extends AbstractView { |
| 05 | // This is were we respond to the MimeType we previously registered |
| 06 | public function canRespondWith(Response $response) { |
| 07 | return 'xls' === $response->request->accepts->format(); |
| 08 | } |
| 09 | |
| 10 | /* Most views render the model in a specific way, a spreadsheet is a little different |
| 11 | * though. I require the xls property to be a two dimensional array containing |
| 12 | * the data to be displayed. |
| 13 | */ |
| 14 | protected function render(Response $response) { |
| 15 | $objPHPExcel = new PHPExcel(); |
| 16 | require_once PHPEXCEL_ROOT . 'PHPExcel/IOFactory.php'; |
| 17 | require_once PHPEXCEL_ROOT . 'PHPExcel/Writer/Excel5.php'; |
| 18 | $objPHPExcel->setActiveSheetIndex(0); |
| 19 | |
| 20 | /* |
| 21 | * The following is loosely based on the JsonView code. If we have a model |
| 22 | * with the xls property set, we create the spreadsheet from that array |
| 23 | */ |
| 24 | $response = clone $response; |
| 25 | foreach($response->data as $key => $value) { |
| 26 | if($value instanceof Model) { |
| 27 | if( isset($value->xls) ) { |
| 28 | foreach($value->xls as $rowId=>$row) { |
| 29 | foreach($row as $colId=>$cell) { |
| 30 | $objPHPExcel->getActiveSheet()->setCellValueByColumnAndRow($colId, $rowId+1, $cell); |
| 31 | } |
| 32 | } |
| 33 | } |
| 34 | } |
| 35 | if($value instanceof Form) { |
| 36 | unset($response->data[$key]); |
| 37 | } |
| 38 | if(substr($key,0,1) == '_') { |
| 39 | unset($response->data[$key]); |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | if(isset($response->data['application'])) unset ($response->data['application']); |
| 44 | if(isset($response->data['controller'])) unset ($response->data['controller']); |
| 45 | |
| 46 | /* I have gone through the docs and can't get ExcelWriter to dump to stdout, |
| 47 | * this way is a little hack I think, but it works. |
| 48 | */ |
| 49 | $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5'); |
| 50 | $tempfile = tempnam('/tmp', 'recessxls'); |
| 51 | $objWriter->save($tempfile); |
| 52 | |
| 53 | // We don't have to mess with headers, Recess! will do that based |
| 54 | // on the registered Mimetype |
| 55 | readfile($tempfile); |
| 56 | } |
| 57 | }; |
| 58 |
So now all our plugins files are setup, and we have to import the plugins into our application. In your app/YourApp/YourAppApplication.class.php add the following lines
| PHP | | copy code | | ? |
| 1 | Library::import('ryanday.PHPExcel.PHPExcelPlugin'); // Add this import |
| 2 | |
| 3 | class YourAppApplication extends Application { |
| 4 | ... |
| 5 | $this->plugins = array(new PHPExcelPlugin()); // instantiate the class to import the library |
| 6 | $this->plugins[0]->init($this); // Important!! |
| 7 | } |
Note the init() call! The MimeType is verified before the plugin is initialized by the Controller. That means the MimeType won’t be registered when the controller looks for it. So we do it ourselves. Finally, in our controller, we create a little example.
| PHP | | copy code | | ? |
| 01 | /** |
| 02 | * !RespondsWith Layouts, Excel |
| 03 | * !Prefix mainModel/ |
| 04 | */ |
| 05 | class MainModelController extends Controller { |
| 06 | |
| 07 | . . . |
| 08 | |
| 09 | /** !Route GET, $id */ |
| 10 | function details($id) { |
| 11 | $this->mainModel->id = $id; |
| 12 | if($this->mainModel->exists()) { |
| 13 | $this->mainModel->xls = array(array("col1","col2","col3"), |
| 14 | array("newrow","newcol","keepgoing"), |
| 15 | array("lastrow","k","lastcol")); |
| 16 | return $this->ok('details'); |
| 17 | } else { |
| 18 | return $this->forwardNotFound($this->urlTo('index')); |
| 19 | } |
| 20 | } |
| 21 |
Now when you visit that particular route, you will get an Excel spreadsheet with the data set in $this->mainModel->xls.
This is just a basic intro on how to create a View plugin. Please comment with any updates, or better way to explain things! This works for me so far, but it hasn’t been tested along a wide distribution of sites.

Thanks for this Recess Plugin example.
Nice to see that belines’s helpful answer to my question about plugins got you inspired to write this plugin. I am still learning and this helps me a lot to get a better understanding of the framework.
Wonderful! It’s was very effective for me. I have used a long time to looking for the best method to learning php easily and now I think I have got something here .BTW, there is another article out there which is also help me much more : http://learning-php-simple.learnmoreskills.com. Hopes you will be interested in it too.