Service tutorial
From PRADO Wiki
Contents |
Introduction
This tutorial will show you how to create a simple service. The service we'll be setting up is a excel reporting service. It will allow users to access a url and receive a generated excel document based on the parameters.
Example: http://localhost/demo/index.php?report=profit&start=20060101&end=20061212
This url would give a profit report starting 01.01.2006, ending 12.12.2006.
The service is based on the feed service created by Knut.
Our service consists of two parts. One TReportDocument, which is a class that our reports will inherit. The other class is our actual service called TReportingService. It handles the logic for us.
TReportDocument
The first code file is our base report. It will inherit TApplicationComponent and expose some properties that all reports share. Format is the file format for the report. The current implementation only support Excel, but formats like PDF and XML should be considered for future revisions. ID holds the ID for the report.
TReportDocument.php source
<?php abstract class TReportDocument extends TApplicationComponent { private $_id=''; private $_format=''; /** * Initializes the feed. * @param TXmlElement configurations specified in {@link TFeedService}. */ public function init($config) { } /** * @return string ID of this feed */ public function getID() { return $this->_id; } /** * @param string ID of this feed */ public function setID($value) { $this->_id=$value; } public function setFormat($value){ $this->_format = $value; } public function getFormat(){ return $this->_format; } /** * @return string an XML string representing the feed content */ public function getReportFile($startdate,$enddate) { return ''; } } ?>
TReportingService.php
Our next code file is the actual reporting service. It loads and parses config from application.xml in the method called init()l What's really happening is that the reports defined in application.xml is stored in $this->_reports. I know the file-download code is a bit dodgy here. This code was written before I actually took a closer look at how Prado handles these kinds of things.
The run() method is invoked when we access http://localhost/demo/index.php?report=whatever. It checks if the supplied report is available, loads the config, creates a instance, initializes the report, then runs $report->getReportFile() if we have the needed parameters to generate the report.
TReportingService.php source
<?php class TReportingService extends TService{ private $_reports=array(); /** * Initializes this module. * This method is required by the IModule interface. * @param TXmlElement configuration for this module, can be null */ public function init($config){ foreach($config->getElementsByTagName('report') as $report){ if(($id=$report->getAttribute('id'))!==null) $this->_reports[$id]=$report; else throw new TConfigurationException('reportservice_id_required'); } } /** * @return string the requested report path */ protected function determineRequestedReportPath(){ return $this->getRequest()->getServiceParameter(); } /** * Runs the service. * This method is invoked by application automatically. */ public function run(){ $id=$this->getRequest()->getServiceParameter(); if(isset($this->_reports[$id])) { $reportConfig=$this->_reports[$id]; $properties=$reportConfig->getAttributes(); if(($class=$properties->remove('class'))!==null){ $report=Prado::createComponent($class); if($report instanceof TReportDocument){ foreach($properties as $name=>$value) $report->setSubproperty($name,$value); $report->init($reportConfig); if (isset($this->Request['startdate']) &&isset($this->Request['enddate']) ){ $file = $report->getReportFile($this->Request['startdate'],$this->Request['enddate']); }else{ throw new TConfigurationException('reportservice_timespan_missing'); } $this->getResponse()->appendHeader("Content-Type: application/x-msexcel; name=\"$file\"\r\n"); $this->getResponse()->appendHeader("Content-Transfer-Encoding: base64\r\n"); $this->getResponse()->appendHeader("Content-Disposition: attachment; filename=\"$file\"\r\n\r\n"); $fh=fopen($file, "rb"); while(!feof($fh)) { $buf = fread($fh, 4096); echo $buf; } fclose($fh); $this->getResponse()->appendHeader("Connection: close"); } else throw new TConfigurationException('reportservice_reporttype_invalid',$id); } else throw new TConfigurationException('reportservice_class_required',$id); } else throw new THttpException(404,'reportservice_report_unknown',$id); } } ?>
A sample report
The next and final code file is the actual report document
ProfitReport.php source
<?php class ProfitReport extends TReportDocument{ private $_id=''; private $_data; /** * Initializes the report * @param TXmlElement configurations specified in {@link TReportingService}. */ public function init($config){ } /** * @return string ID of this report */ public function getID(){ return $this->_id; } /** * @param string ID of this report */ public function setID($value){ $this->_id=$value; } /** * @return string filename of the new report */ public function getReportFile($startdate,$enddate){ if ($this->Format != "xls") // we do not support anything else yet:) throw new TConfigurationException('reportservice_unsupported_format',$this->Format); return $this->generateExcelDocument($startdate,$enddate); } private function loadData($startdate,$enddate){ // load data $this->_data = $loadedData; } public function generateExcelDocument($startdate,$enddate){ $this->loadData($startdate,$enddate); // create excel document // write data to document // return path to document return $filename; } } ?>
Setting up the service in application.xml
The last thing we need to do is set the service up in application.xml. Thats pretty simple:
<service id="report" class="TReportingService"> <report id="profit" class="ProfitReport" format="xls"/> </service>
Future work
This tutorial will be updated with a functional sample service asap.

