Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Zend Framework Service

DragonBe
February 04, 2013

Zend Framework Service

Using the power of Zend Framework to build a SOA application

DragonBe

February 04, 2013
Tweet

More Decks by DragonBe

Other Decks in Technology

Transcript

  1. WARNING Used Environment PHP 5.3.1 Zend Framework 1.10.3 MySQL 5.1.32

    Examples might not work on another environment
  2. Michelangelo van Dam • Independent Consultant • Zend Certified Engineer

    (ZCE) - PHP 4 & PHP 5 - Zend Framework • Co-Founder of PHPBenelux • Shepherd of “elephpant” herds
  3. What is Zend Framework A loosly-coupled framework with a flexible

    architecture that lets you easily build modern web applications and web services Matthew Weier O’Phinney - Chief Architect Zend Framework
  4. Why a service ? • opening up existing API -

    internal applications - external applications - additional functionality • support to more devices • portability and flexibility
  5. Important components • Zend_Soap - Zend_Soap_Server - Zend_Soap_Client - Zend_Soap_Wsdl

    • Zend_Rest - Zend_Rest_Server - Zend_Rest_Client • Zend_XmlRpc - Zend_XmlRpc_Server - Zend_XmlRpc_Client - Zend_XmlRpc_Request - Zend_XmlRpc_Response
  6. Example service • Time registration - list time sheets -

    add a new task - edit an existing task - delete an existing task
  7. MVC approach • time module - controllers (for displaying listing

    and forms) - actions (for listing, adding, editing and deleting) - models (for access to database) - forms (for filtering, validation and rendering forms)
  8. Common behavior • all “logic” is put in the controller

    • actions = API interface • downside - not flexible towards other clients - difficult to provide maintenance - not reusable design
  9. Time_IndexController Time Module indexAction - lists registered tasks - links

    to the form - for adding task - for editing task - for deleting task editAction - displays a form - for adding task - for editing task registerAction - processes form data - validating data - storing data in db deleteAction - deletes task
  10. API Design • moving logic - out the controller -

    in an API class • structures the application • is better testable • is better maintainable
  11. My_Api_Timesheet Time API listTasks - lists registered tasks registerNewTask -

    for adding task editExistingTask - for modifying task deleteExistingTask - deletes task
  12. DocBlocks are important! • DocBlocks are very important ! -

    provide quality API documentation - can be used as reference for the server !!!
  13. listTasks /** * List all tasks for a given user

    * * @param int $user * @return array */ public function listTasks($user) { $array = array (); $timesheet = new Time_Model_Timesheet(); if (null !== ($result = $timesheet->fetchAll(array ( 'user_id = ?' => $user, ), array ('date DESC', 'start_time ASC')))) { foreach ($result as $entry) { $array[] = $entry->toArray(); } } return $array; }
  14. registerNewTask /** * Register a new task * * @param

    int $user The ID of the user * @param int $customer The ID of the customer * @param int $task The ID of the task * @param string $date A date formatted as YYYY-mm-dd * @param string $start The starting time as HH:mm:ss * @param string $end The ending time as HH:mm:ss * @param string $description A short description * @return bool TRUE if registration succeeded * @throws My_Api_Timesheet_Exception */
  15. registerNewTask public function registerNewTask( $user, $customer, $task, $date, $start, $end,

    $description) { $timesheet = new Time_Model_Timesheet(); $timesheet->setUserId($user) ->setCustomerId($customer) ->setTaskId($task) ->setDate($date) ->setStartTime($start) ->setEndTime($end) ->setDescription($description); $validator = $this->_validate($timesheet); if (false === $validator) { require_once 'My/Api/Timesheet/Exception.php'; throw new My_Api_Timesheet_Exception('Invalid data provided'); } $timesheet->save(); return true; }
  16. editExistingTask /** * Modify an existing task * * @param

    int $id The ID of an existing Task * @param int $user The ID of the user * @param int $customer The ID of the customer * @param int $task The ID of the task * @param string $date A date formatted as YYYY-mm-dd * @param string $start The starting time as HH:mm:ss * @param string $end The ending time as HH:mm:ss * @param string $description A short description * @return bool TRUE if registration succeeded * @throws My_Api_Timesheet_Exception */
  17. editExistingTask public function editExistingTask( $id, $user, $customer, $task, $date, $start,

    $end, $description) { $timesheet = new Time_Model_Timesheet(); $timesheet->setId($id) ->setUserId($user) ->setCustomerId($customer) ->setTaskId($task) ->setDate($date) ->setStartTime($start) ->setEndTime($end) ->setDescription($description); $validator = $this->_validate($timesheet); if (false === $validator) { require_once 'My/Api/Timesheet/Exception.php'; throw new My_Api_Timesheet_Exception('Invalid data provided'); } $timesheet->save(); return true; }
  18. deleteExistingTask /** * Modify an existing task * * @param

    int $id The ID of an existing Task * @param int $user The ID of the user * @return bool TRUE if registration succeeded * @throws My_Api_Timesheet_Exception */ public function deleteExistingTask($id, $user) { $timesheet = new Time_Model_Timesheet(); $timesheet->setId($id) ->setUserId($user); $validator = $this->_validate($timesheet); if (false === $validator) { require_once 'My/Api/Timesheet/Exception.php'; throw new My_Api_Timesheet_Exception('Invalid data provided'); } $timesheet->delete(array ( 'id = ?' => $timesheet->getId(), 'user_id = ?' => $timesheet->getUserId(), )); return true; }
  19. _validate /** * Private validation method * * @param Time_Model_Timesheet

    $timesheet * @return bool TRUE if validated, FALSE if invalid */ private function _validate(Time_Model_Timesheet $timesheet) { $result = true; $validator = new Time_Form_Register(); $customer = new Time_Model_Customer(); $task = new Time_Model_Task(); $validator->getElement('customer_id')->setMultiOptions($customer->toSelect()); $validator->getElement('task_id')->setMultiOptions($task->toSelect()); if (!$validator->isValid($timesheet->toArray())) { $result = false; } return $result; }
  20. XmlRpc Server <?php class Time_XmlRpcController extends Zend_Controller_Action { public function

    indexAction() { $this->_helper->layout()->disableLayout(); $this->_helper->viewRenderer->setNoRender(true); require_once 'My/Api/Timesheet.php'; $server = new Zend_XmlRpc_Server(); $server->setClass('My_Api_Timesheet'); echo $server->handle(); } }
  21. SOAP Server <?php class Time_SoapController extends Zend_Controller_Action { public function

    indexAction() { $this->_helper->layout()->disableLayout(); $this->_helper->viewRenderer->setNoRender(true); $options = array (); $server = new Zend_Soap_AutoDiscover(); $server->setClass('My_Api_Timesheet'); $server->handle(); } }
  22. SOAP Client <?php class Time_SoapClientController extends Zend_Controller_Action { protected $_client;

    public function init() { $this->_helper->layout()->disableLayout(); $this->_helper->viewRenderer->setNoRender(true); $this->_client = new Zend_Soap_Client( 'http://www.demo.local/Time/soap?wsdl', array ()); } public function indexAction() { Zend_Debug::dump($this->_client->listTasks(2)); } public function addAction() { Zend_Debug::dump($this->_client->registerNewTask( 2, 2, 3, '2010-03-30', '18:00:00', '23:30:00','Setting up SOAP')); } public function editAction() { Zend_Debug::dump($this->_client->editExistingTask( 7, 2, 2, 3, '2010-03-30', '18:00:00', '23:30:00','Testing SOAP')); } public function deleteAction() { Zend_Debug::dump($this->_client->deleteExistingTask(7, 2)); } }
  23. REST Server <?php class Time_RestController extends Zend_Controller_Action { public function

    indexAction() { $this->_helper->layout()->disableLayout(); $this->_helper->viewRenderer->setNoRender(true); $server = new Zend_Rest_Server(); $server->setClass('My_Api_Timesheet'); $server->handle(); } }
  24. REST Client <?php class Time_RestClientController extends Zend_Controller_Action { protected $_client;

    public function init() { $this->_helper->layout()->disableLayout(); $this->_helper->viewRenderer->setNoRender(true); $this->_client = new Zend_Rest_Client('http://www.demo.local/Time/rest'); } public function indexAction() { $this->_client->listTasks(2); Zend_Debug::dump($this->_client->get()); } }
  25. Conclusion moving functionality out the controller into a library API

    = saves time 1 api = XmlRpc + SOAP + REST + …
  26. You can help ! • find a bug ? -

    test it - report it - send a patch/fix • need a non-existing component - submit proposal • like Zend Framework - blog about it - talk about it
  27. ZF Bug hunt days Zend Framework Bughuntdays every 3rd Thursday

    and Friday of the month http://framework.zend.com/issues IRC (irc.freenode.net) #zftalk.dev prizes: Free subscription for 1 year on php|Architect magazine Zend Framework t-shirt recognition and appreciation of the community