SlideShare una empresa de Scribd logo
1 de 50
Descargar para leer sin conexión
Zend Framework
“at your service”
   Michelangelo van Dam
   Macq Electronique 2010, Brussels
WARNING

            Used Environment
                  PHP 5.3.2
            Zend Framework 1.10.4
                MySQL 5.1.32


Examples might not work on another environment
Michelangelo van Dam

• Independent Consultant
• Zend Certified Engineer (ZCE)
 - PHP 4 & PHP 5
 - Zend Framework
• Co-Founder of PHPBenelux
• Shepherd of “elephpant” herds
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
Why a service ?
•- opening up existing API
   internal applications
 - external applications
 - additional functionality
• support to more devices
• portability and flexibility
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
Example service
•- Time registration
     list time sheets
 -   add a new task
 -   edit an existing task
 -   delete an existing task
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)
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
Time Module
              Time_IndexController
 indexAction                editAction
- lists registered tasks   - displays a form
- links to the form          - for adding task
  - for adding task          - for editing task
  - for editing task
  - for deleting task


 registerAction             deleteAction
- processes form data      - deletes task
  - validating data
  - storing data in db
API Design
•- moving logic
    out the controller
 - in an API class
• structures the application
• is better testable
• is better maintainable
Time API
                My_Api_Timesheet
 listTasks                  registerNewTask
- lists registered tasks   - for adding task




 editExistingTask           deleteExistingTask
- for modifying task       - deletes task
Simple ?
API output channels
 Web    Internal    SOAP




 XML    API        XMLRPC




 JSON     …         REST
Timesheet API
DocBlocks are important!
•- DocBlocks are very important !
     provide quality API documentation
 -   can be used as reference for the service !!!
Automated API docs
My_Api_Timesheet
<?php
class My_Api_Timesheet
{
}
listTasks
/**
  * List all tasks for a given user
  *
  * @param int $user
  * @param int $limit
  * @return array
  */
public function listTasks($user, $limit = null)
{
	 $array = array ();
	 $timesheet = new Time_Model_Timesheet();
	 if (null !== ($result = $timesheet->fetchAll(array (
	 	 'user_id = ?' => $user,
	 ), array ('date DESC', 'start_time ASC'), $limit))) {
	 	 foreach ($result as $entry) {
	 	 	 $array[] = $entry->toArray();
	 	 }
	 }
	 return $array;
}
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
 */
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;
}
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
 */
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;
}
deleteExistingTask
/**
  * Removes 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
  */
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;
}
_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;
}
Zend_XmlRpc
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();
    }
}
XmlRpc Client
<?php
class Time_XmlRpcClientController
      extends Zend_Controller_Action
{
    protected $_client;

    public function init()
    {
        $this->_helper->layout()->disableLayout();
        $this->_helper->viewRenderer->setNoRender(true);
        $this->_client = new Zend_XmlRpc_Client(
            'http://www.demo.local/Time/XmlRpc');
    }
…
}
XmlRpc Client
public function newAction()
{
    	
    $client = $this->_client;
    	
    $request = new Zend_XmlRpc_Request();
    	
    $request->setMethod('registerNewTask');
    	
    $request->setParams(array (
    	
    	    2,	 	    	   	    	   // user ID
    	
    	    3,	 	    	   	    	   // customer ID
    	
    	    3,	 	    	   	    	   // task ID
    	
    	    '2010-03-28',	
                      	    // date
    	
    	    '18:00:00',	 	    	   // start time
    	
    	    '23:30:00',	 	    	   // end time
    	
    	    'Demo XmlRpc add',	   // description
    	
    ));
    	
    $result = null;
    	
    $errors = array ();
    	
    try {
    	
    	    $client->doRequest($request);
    	
    	    $result = $client->getLastResponse()->getReturnValue();
    	 catch (Zend_XmlRpc_Client_FaultException $e) {
    }
    	
    	    $errors['fault'] = "[{$e->getCode()}]: {$e->getMessage()}";
    	 catch (Zend_XmlRpc_Client_HttpException $e) {
    }
    	
    	    $errors['http'] = "[{$e->getCode()}]: {$e->getMessage()}";
    	 catch (My_Api_Timesheet_Exception $e) {
    }
    	
    	    $errors['api'] = "[{$e->getCode()}]: {$e->getMessage()}";
    	
    }
}
XmlRpc Client
public function editAction()
{
    	$client = $this->_client;
    	$request = new Zend_XmlRpc_Request();
    	$request->setMethod('editExistingTask');
    	$request->setParams(array (
    		    5,	 	     	    	    	    // ID
    		    2,	 	     	    	    	    // user ID
    		    3,	 	     	    	    	    // customer ID
    		    4,	 	     	    	    	    // task ID
    		    '2010-03-28',	 	    // date
    		    '18:00:00',	 	      	    // start time
    		    '23:30:00',	 	      	    // end time
    		    'Demo XmlRpc add',	 // description
    	));
    	$result = null;
    	$errors = array ();
    	try {
    		    $client->doRequest($request);
    		    $result = $client->getLastResponse()->getReturnValue();
    	} catch (Zend_XmlRpc_Client_FaultException $e) {
    		    $errors['fault'] = "[{$e->getCode()}]: {$e->getMessage()}";
    	} catch (Zend_XmlRpc_Client_HttpException $e) {
    		    $errors['http'] = "[{$e->getCode()}]: {$e->getMessage()}";
    	} catch (My_Api_Timesheet_Exception $e) {
    		    $errors['api'] = "[{$e->getCode()}]: {$e->getMessage()}";
    	}
}
XmlRpc Client
public function deleteAction()
{
    	
    $client = $this->_client;
    	
    $request = new Zend_XmlRpc_Request();
    	
    $request->setMethod('deleteExistingTask');
    	
    $request->setParams(array (
    	
    	    6,	 	    	   	   	    // ID
    	
    	    2,	 	    	   	   	    // user ID
    	
    ));
    	
    $result = null;
    	
    $errors = array ();
    	
    try {
    	
    	    $client->doRequest($request);
    	
    	    $result = $client->getLastResponse()->getReturnValue();
    	
    	    if ($client->getLastResponse()->isFault()) {
    	
    	    	   $result = $client->getLastResponse()->getFault();
    	
    	    }
    	 catch (Zend_XmlRpc_Client_FaultException $e) {
    }
    	
    	    $errors['fault'] = "[{$e->getCode()}]: {$e->getMessage()}";
    	 catch (Zend_XmlRpc_Client_HttpException $e) {
    }
    	
    	    $errors['http'] = "[{$e->getCode()}]: {$e->getMessage()}";
    	 catch (My_Api_Timesheet_Exception $e) {
    }
    	
    	    $errors['api'] = "[{$e->getCode()}]: {$e->getMessage()}";
    	
    }
}
Zend_Soap
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();
    }
}
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()
     {
        $result = $this->_client->listTasks(2, 2);
	   	 $this->getResponse()->setHeader('Content-Type', 'text/xml; Charset=UTF-8');
     	 echo $this->_client->getLastResponse();
     }
…
SOAP Client
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));
    }
}
Zend_Rest
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();
    }
}
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());
     }
}
Patterns ???
Conclusion

moving functionality out the controller
          into a library API
                   =
              saves time

1 api = XmlRpc + SOAP + REST + …
Recommended reading
    Web Services Essentials
    Ethan Cerami

    O’Reilly



    Programming Web Services with XML-RPC
    Simon St. Laurent, Joe Johnston, Edd Dumbill,
    Dave Winer

    O’Reilly
Recommended reading
    RESTful Web Services
    Leonard Richardson, Sam Ruby

    O’Reilly



    Programming Web Services with XML-RPC
    James Snell, Doug Tidwell, Pavel Kulchenko

    O’Reilly
We need you help !!!
Feedback is important
•- 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
• translations
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:
    recognition and appreciation of the community
Free subscription for 1 year on php|Architect magazine
                Zend Framework t-shirt
ZF issue tracker
• When: June 10 - 12 2010
• Where: Amsterdam RAI
• Tickets: http://phpconference.nl
 • Early bird: ends April 30, 2010 (Queen’s Day)
PHP
                              BENELUX



• annual event
• improve code coverage
• test php core source code
• improve quality of PHP
PHP
                           BENELUX


• When: May 29, 2010
• Where: <to-be-defined>
• Updates:
 • web: http://www.phpbenelux.eu
 • twitter: @phpbenelux
Thank you !


         Slides on Slideshare
http://www.slideshare.net/group/macqel

      Give feedback on Joind.in
         http://joind.in/1263

Más contenido relacionado

La actualidad más candente

ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf Conference
 
Dealing with Legacy PHP Applications
Dealing with Legacy PHP ApplicationsDealing with Legacy PHP Applications
Dealing with Legacy PHP Applications
Clinton Dreisbach
 

La actualidad más candente (20)

The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et Pimple
 
When cqrs meets event sourcing
When cqrs meets event sourcingWhen cqrs meets event sourcing
When cqrs meets event sourcing
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
 
購物車程式架構簡介
購物車程式架構簡介購物車程式架構簡介
購物車程式架構簡介
 
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needDutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and Hobgoblins
 
Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome Town
 
PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2
 
Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il cliente
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patterns
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technology
 
CQRS and Event Sourcing in a Symfony application
CQRS and Event Sourcing in a Symfony applicationCQRS and Event Sourcing in a Symfony application
CQRS and Event Sourcing in a Symfony application
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
 
Symfony CoP: Form component
Symfony CoP: Form componentSymfony CoP: Form component
Symfony CoP: Form component
 
Dealing with Legacy PHP Applications
Dealing with Legacy PHP ApplicationsDealing with Legacy PHP Applications
Dealing with Legacy PHP Applications
 
Introduction to CQRS and Event Sourcing
Introduction to CQRS and Event SourcingIntroduction to CQRS and Event Sourcing
Introduction to CQRS and Event Sourcing
 

Similar a Introduction to Zend Framework web services

Similar a Introduction to Zend Framework web services (20)

Zend framework service
Zend framework serviceZend framework service
Zend framework service
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hacking
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4Developers
 
ZF2 for the ZF1 Developer
ZF2 for the ZF1 DeveloperZF2 for the ZF1 Developer
ZF2 for the ZF1 Developer
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ Etsy
 
Bag Of Tricks From Iusethis
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From Iusethis
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8
 
Bacbkone js
Bacbkone jsBacbkone js
Bacbkone js
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenarios
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
Rails is not just Ruby
Rails is not just RubyRails is not just Ruby
Rails is not just Ruby
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 
The Zen of Lithium
The Zen of LithiumThe Zen of Lithium
The Zen of Lithium
 
Easy rest service using PHP reflection api
Easy rest service using PHP reflection apiEasy rest service using PHP reflection api
Easy rest service using PHP reflection api
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your Code
 
Clean Javascript
Clean JavascriptClean Javascript
Clean Javascript
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hacking
 

Más de Michelangelo van Dam

Zf2 how arrays will save your project
Zf2   how arrays will save your projectZf2   how arrays will save your project
Zf2 how arrays will save your project
Michelangelo van Dam
 

Más de Michelangelo van Dam (20)

GDPR Art. 25 - Privacy by design and default
GDPR Art. 25 - Privacy by design and defaultGDPR Art. 25 - Privacy by design and default
GDPR Art. 25 - Privacy by design and default
 
Moving from app services to azure functions
Moving from app services to azure functionsMoving from app services to azure functions
Moving from app services to azure functions
 
Privacy by design
Privacy by designPrivacy by design
Privacy by design
 
DevOps or DevSecOps
DevOps or DevSecOpsDevOps or DevSecOps
DevOps or DevSecOps
 
Privacy by design
Privacy by designPrivacy by design
Privacy by design
 
Continuous deployment 2.0
Continuous deployment 2.0Continuous deployment 2.0
Continuous deployment 2.0
 
Let your tests drive your code
Let your tests drive your codeLet your tests drive your code
Let your tests drive your code
 
General Data Protection Regulation, a developer's story
General Data Protection Regulation, a developer's storyGeneral Data Protection Regulation, a developer's story
General Data Protection Regulation, a developer's story
 
Leveraging a distributed architecture to your advantage
Leveraging a distributed architecture to your advantageLeveraging a distributed architecture to your advantage
Leveraging a distributed architecture to your advantage
 
The road to php 7.1
The road to php 7.1The road to php 7.1
The road to php 7.1
 
Open source for a successful business
Open source for a successful businessOpen source for a successful business
Open source for a successful business
 
Decouple your framework now, thank me later
Decouple your framework now, thank me laterDecouple your framework now, thank me later
Decouple your framework now, thank me later
 
Deploy to azure in less then 15 minutes
Deploy to azure in less then 15 minutesDeploy to azure in less then 15 minutes
Deploy to azure in less then 15 minutes
 
Azure and OSS, a match made in heaven
Azure and OSS, a match made in heavenAzure and OSS, a match made in heaven
Azure and OSS, a match made in heaven
 
Getting hands dirty with php7
Getting hands dirty with php7Getting hands dirty with php7
Getting hands dirty with php7
 
Zf2 how arrays will save your project
Zf2   how arrays will save your projectZf2   how arrays will save your project
Zf2 how arrays will save your project
 
Create, test, secure, repeat
Create, test, secure, repeatCreate, test, secure, repeat
Create, test, secure, repeat
 
The Continuous PHP Pipeline
The Continuous PHP PipelineThe Continuous PHP Pipeline
The Continuous PHP Pipeline
 
PHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsPHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the tests
 
Easily extend your existing php app with an api
Easily extend your existing php app with an apiEasily extend your existing php app with an api
Easily extend your existing php app with an api
 

Último

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 

Último (20)

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 

Introduction to Zend Framework web services

  • 1. Zend Framework “at your service” Michelangelo van Dam Macq Electronique 2010, Brussels
  • 2. WARNING Used Environment PHP 5.3.2 Zend Framework 1.10.4 MySQL 5.1.32 Examples might not work on another environment
  • 3. Michelangelo van Dam • Independent Consultant • Zend Certified Engineer (ZCE) - PHP 4 & PHP 5 - Zend Framework • Co-Founder of PHPBenelux • Shepherd of “elephpant” herds
  • 4. 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
  • 5. Why a service ? •- opening up existing API internal applications - external applications - additional functionality • support to more devices • portability and flexibility
  • 6. 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
  • 7. Example service •- Time registration list time sheets - add a new task - edit an existing task - delete an existing task
  • 8. 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)
  • 9. 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
  • 10. Time Module Time_IndexController indexAction editAction - lists registered tasks - displays a form - links to the form - for adding task - for adding task - for editing task - for editing task - for deleting task registerAction deleteAction - processes form data - deletes task - validating data - storing data in db
  • 11. API Design •- moving logic out the controller - in an API class • structures the application • is better testable • is better maintainable
  • 12. Time API My_Api_Timesheet listTasks registerNewTask - lists registered tasks - for adding task editExistingTask deleteExistingTask - for modifying task - deletes task
  • 14. API output channels Web Internal SOAP XML API XMLRPC JSON … REST
  • 16. DocBlocks are important! •- DocBlocks are very important ! provide quality API documentation - can be used as reference for the service !!!
  • 19. listTasks /** * List all tasks for a given user * * @param int $user * @param int $limit * @return array */ public function listTasks($user, $limit = null) { $array = array (); $timesheet = new Time_Model_Timesheet(); if (null !== ($result = $timesheet->fetchAll(array ( 'user_id = ?' => $user, ), array ('date DESC', 'start_time ASC'), $limit))) { foreach ($result as $entry) { $array[] = $entry->toArray(); } } return $array; }
  • 20. 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 */
  • 21. 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; }
  • 22. 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 */
  • 23. 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; }
  • 24. deleteExistingTask /** * Removes 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 */ 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; }
  • 25. _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; }
  • 27. 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(); } }
  • 28. XmlRpc Client <?php class Time_XmlRpcClientController extends Zend_Controller_Action { protected $_client; public function init() { $this->_helper->layout()->disableLayout(); $this->_helper->viewRenderer->setNoRender(true); $this->_client = new Zend_XmlRpc_Client( 'http://www.demo.local/Time/XmlRpc'); } … }
  • 29. XmlRpc Client public function newAction() { $client = $this->_client; $request = new Zend_XmlRpc_Request(); $request->setMethod('registerNewTask'); $request->setParams(array ( 2, // user ID 3, // customer ID 3, // task ID '2010-03-28', // date '18:00:00', // start time '23:30:00', // end time 'Demo XmlRpc add', // description )); $result = null; $errors = array (); try { $client->doRequest($request); $result = $client->getLastResponse()->getReturnValue(); catch (Zend_XmlRpc_Client_FaultException $e) { } $errors['fault'] = "[{$e->getCode()}]: {$e->getMessage()}"; catch (Zend_XmlRpc_Client_HttpException $e) { } $errors['http'] = "[{$e->getCode()}]: {$e->getMessage()}"; catch (My_Api_Timesheet_Exception $e) { } $errors['api'] = "[{$e->getCode()}]: {$e->getMessage()}"; } }
  • 30. XmlRpc Client public function editAction() { $client = $this->_client; $request = new Zend_XmlRpc_Request(); $request->setMethod('editExistingTask'); $request->setParams(array ( 5, // ID 2, // user ID 3, // customer ID 4, // task ID '2010-03-28', // date '18:00:00', // start time '23:30:00', // end time 'Demo XmlRpc add', // description )); $result = null; $errors = array (); try { $client->doRequest($request); $result = $client->getLastResponse()->getReturnValue(); } catch (Zend_XmlRpc_Client_FaultException $e) { $errors['fault'] = "[{$e->getCode()}]: {$e->getMessage()}"; } catch (Zend_XmlRpc_Client_HttpException $e) { $errors['http'] = "[{$e->getCode()}]: {$e->getMessage()}"; } catch (My_Api_Timesheet_Exception $e) { $errors['api'] = "[{$e->getCode()}]: {$e->getMessage()}"; } }
  • 31. XmlRpc Client public function deleteAction() { $client = $this->_client; $request = new Zend_XmlRpc_Request(); $request->setMethod('deleteExistingTask'); $request->setParams(array ( 6, // ID 2, // user ID )); $result = null; $errors = array (); try { $client->doRequest($request); $result = $client->getLastResponse()->getReturnValue(); if ($client->getLastResponse()->isFault()) { $result = $client->getLastResponse()->getFault(); } catch (Zend_XmlRpc_Client_FaultException $e) { } $errors['fault'] = "[{$e->getCode()}]: {$e->getMessage()}"; catch (Zend_XmlRpc_Client_HttpException $e) { } $errors['http'] = "[{$e->getCode()}]: {$e->getMessage()}"; catch (My_Api_Timesheet_Exception $e) { } $errors['api'] = "[{$e->getCode()}]: {$e->getMessage()}"; } }
  • 33. 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(); } }
  • 34. 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() { $result = $this->_client->listTasks(2, 2); $this->getResponse()->setHeader('Content-Type', 'text/xml; Charset=UTF-8'); echo $this->_client->getLastResponse(); } …
  • 35. SOAP Client 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)); } }
  • 37. 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(); } }
  • 38. 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()); } }
  • 40. Conclusion moving functionality out the controller into a library API = saves time 1 api = XmlRpc + SOAP + REST + …
  • 41. Recommended reading Web Services Essentials Ethan Cerami O’Reilly Programming Web Services with XML-RPC Simon St. Laurent, Joe Johnston, Edd Dumbill, Dave Winer O’Reilly
  • 42. Recommended reading RESTful Web Services Leonard Richardson, Sam Ruby O’Reilly Programming Web Services with XML-RPC James Snell, Doug Tidwell, Pavel Kulchenko O’Reilly
  • 43. We need you help !!!
  • 44. Feedback is important •- 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 • translations
  • 45. 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: recognition and appreciation of the community Free subscription for 1 year on php|Architect magazine Zend Framework t-shirt
  • 47. • When: June 10 - 12 2010 • Where: Amsterdam RAI • Tickets: http://phpconference.nl • Early bird: ends April 30, 2010 (Queen’s Day)
  • 48. PHP BENELUX • annual event • improve code coverage • test php core source code • improve quality of PHP
  • 49. PHP BENELUX • When: May 29, 2010 • Where: <to-be-defined> • Updates: • web: http://www.phpbenelux.eu • twitter: @phpbenelux
  • 50. Thank you ! Slides on Slideshare http://www.slideshare.net/group/macqel Give feedback on Joind.in http://joind.in/1263