Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Into the ZF2 Service Manager

1,123 views

Published on

One of the most prolific parts of Zend Framework 2 is the Service Manager. Its many nooks and crannies dictate much of what happens inside our Zend Framework 2 applications and is incredibly powerful. Let's look into exactly what the Service Manager allows us to do and how we can take advantage of it for cleaner, and faster, code.

Published in: Technology
  • Be the first to comment

Into the ZF2 Service Manager

  1. 1. Into the ZF2 Service Manager Chris  Tankersley   ZendCon  2015   ZendCon  2015   1  
  2. 2. Who Am I •  PHP  Programmer  for  over  10  years   •  Been  using  ZF  since  ~0.5   •  Daily  ZF2  user   •  hBps://github.com/dragonmantank   ZendCon  2015   2  
  3. 3. A running joke… •  “Symfony2  is  a  PHP  script  that  turns  YAML  into  applicaNons”   •  “Yeah,  but  Zend  Framework  2  is  a  PHP  script  that  turns  arrays  into   applicaNons”   ZendCon  2015   3  
  4. 4. ZendCon  2015   4  
  5. 5. It kind of is… ZendCon  2015   5   return  [          'service_manager'  =>  [                  'initializers'  =>  [                          'JobServiceJobServiceAwareInitializer'                  ],                  'invokables'  =>  [                          'JobProcessorListener'  =>  'JobProcessorProcessorListener',                          'JobServiceAccountListener'  =>  'JobServiceJobServiceListener’                      ],                  'factories'  =>  [                          'JobService'                      =>  'JobServiceJobServiceFactory',                          'JobProcessor'                  =>  'JobProcessorProcessorFactory',                  ]          ]   ]  
  6. 6. Theater Magic •  When  something  awesome  happens,  but  it’s  really  something   mundane  controlling  it  in  the  background   •  When  it  looks  good  from  25’   ZendCon  2015   6  
  7. 7. The Service Manager ZendCon  2015   7  
  8. 8. Service Locator •  Container  for  storing  objects  or  condiNons  for  building  an  object   •  Mostly  it’s  used  to  create  objects   •  It  does  not  do  automaNc  dependency  injecNon   •  It  is  not  global  (unless  you  make  it  global)   ZendCon  2015   8  
  9. 9. What can we store in there? •  Invokables   •  Factories   •  Abstract  Factories   •  Delegators   •  IniNalizers   •  Aliases   ZendCon  2015   9  
  10. 10. Standalone $serviceManager  =  new  ZendServiceManagerServiceManager();   $serviceManager-­‐>setService(‘MyService’,  $myService);     $serviceManager-­‐>has(‘MyService’);   $service  =  $serviceManager-­‐>get(‘MyService’);     ZendCon  2015   10  
  11. 11. Built into ZF2 full-stack applications •  Anything  that  is  ServiceLocatorAwareInterface  can  have  it  injected   •  Controllers  are  the  most  common   ZendCon  2015   11   namespace  ApplicationController;     use  ZendMvcControllerAbstractActionController;     class  IndexController  extends  AbstractActionController  {          public  function  indexAction()  {                  $model  =  $this-­‐>getServiceLocator()-­‐>get(‘MyModel’);          }   }  
  12. 12. Stuff we can get from the Service Manager ZendCon  2015   12  
  13. 13. Invokables •  Any  sort  of  object  that  can  be  declared  with  ‘new’  and  has  no   constructor  parameters   ZendCon  2015   13   class  MyClass  {          public  function  foo()  {  ...  }          public  function  bar()  {  ...  }   }     class  SimpleConstructor  {          protected  $name;          public  function  __construct()  {                  $this-­‐>name  =  'baz';          }   }  
  14. 14. In ZF2 return  [          'service_manager'  =>  [                  'invokables'  =>  [                          'JobProcessorProcessorListener'  =>  'JobProcessorProcessorListener',                          'JobServiceAccountListener'  =>  'JobServiceJobServiceListener'                  ],          ]   ]   ZendCon  2015   14  
  15. 15. Quick Dependency Injection Tutorial ZendCon  2015   15  
  16. 16. What is Dependency Injection? •  InjecNng  dependencies  into  classes,  instead  of  having  the  class  create   it   •  Allows  for  much  easier  tesNng   •  Allows  for  a  much  easier  Nme  swapping  out  code   •  Reduces  the  coupling  that  happens  between  classes   php[tek]  2015   16  
  17. 17. Method Injection class  MapService  {          public  function  getLatLong(GoogleMaps  $map,  $street,  $city,  $state)  {                  return  $map-­‐>getLatLong($street  .  '  '  .  $city  .  '  '  .  $state);          }                    public  function  getAddress(GoogleMaps  $map,  $lat,  $long)  {                  return  $map-­‐>getAddress($lat,  $long);          }   }   php[tek]  2015   17  
  18. 18. Constructor Injection class  MapService  {          protected  $map;          public  function  __construct(GoogleMaps  $map)  {                  $this-­‐>map  =  $map;          }          public  function  getLatLong($street,  $city,  $state)  {                  return  $this                          -­‐>map                          -­‐>getLatLong($street  .  '  '  .  $city  .  '  '  .  $state);          }   }         php[tek]  2015   18  
  19. 19. Setter Injection class  MapService  {          protected  $map;                    public  function  setMap(GoogleMaps  $map)  {                  $this-­‐>map  =  $map;          }          public  function  getMap()  {                  return  $this-­‐>map;          }          public  function  getLatLong($street,  $city,  $state)  {                  return  $this-­‐>getMap()-­‐>getLatLong($street  .  '  '  .  $city  .  '  '  .  $state);          }   }       php[tek]  2015   19  
  20. 20. Back to the show ZendCon  2015   20  
  21. 21. Factories •  A  Factory  is  an  object/method  is  that  is  used  to  create  other  objects   •  ZF2  Service  Manager  will  call  the  factory  when  an  object  is  pulled  out   of  the  Service  Manager   ZendCon  2015   21  
  22. 22. Why do we need factories? Dependencies   ZendCon  2015   22  
  23. 23. In ZF2 ZendCon  2015   23   return  [          'service_manager'  =>  [                  ’factories'  =>  [                          'GoogleAdWordsAdWordsUserBuilder'  =>  'GoogleAdWordsGoogleAdWordsUserBuilderFactory',                  ],          ]   ]  
  24. 24. ZendCon  2015   24   namespace  GoogleAdWords;     class  GoogleAdWordsUserBuilder   {          public  function  __construct(array  $config)  {                  $this-­‐>config  =  $config;          }   }    
  25. 25. ZendCon  2015   25   namespace  GoogleAdWords;     use  ZendServiceManagerFactoryInterface;   use  ZendServiceManagerServiceLocatorInterface;     class  GoogleAdWordsUserBuilderFactory  implements  FactoryInterface   {          public  function  createService(ServiceLocatorInterface  $service)          {                  $config  =  $service-­‐>get('Config');                  return  new  GoogleAdWordsUserBuilder($config[‘google’]);          }   }    
  26. 26. Abstract Factories •  They  are  factories,  but  they  allow  the  creaNon  of  a  broad  range  of   objects  instead  of  a  single  object   •  The  factory  will  take  addiNonal  configuraNon  to  properly  create  the   needed  object   ZendCon  2015   26  
  27. 27. ZendCon  2015   27   <?php     namespace  MyProject;     use  ZendDbTableGatewayTableGateway;   use  ZendServiceManagerFactoryInterface;   use  ZendServiceManagerServiceLocatorInterface;     class  ProjectsTableFactory  implements  FactoryInterface  {          public  function  createService(ServiceLocatorInterface  $serviceLocator)  {                  $adapter  =  new  $serviceLocator-­‐>get('ZendDbAdapterAdapter');                  return  new  TableGateway('projects',  $adapter);          }   }     class  CategoriesTableFactory  implements  FactoryInterface  {          public  function  createService(ServiceLocatorInterface  $serviceLocator)  {                  $adapter  =  new  $serviceLocator-­‐>get('ZendDbAdapterAdapter');                  return  new  TableGateway('categories',  $adapter);          }   }  
  28. 28. In ZF2 ZendCon  2015   28   return  [          ’abstract_factories'  =>  [                  ’MyProjectTableAbstractFactory’          ]   ]  
  29. 29. ZendCon  2015   29   <?php     namespace  MyProject;     use  ZendDbTableGatewayTableGateway;   use  ZendServiceManagerAbstractFactoryInterface;   use  ZendServiceManagerServiceLocatorInterface;     class  TableAbstractFactory  implements  AbstractFactoryInterface  {          public  function  canCreateServiceWithName(ServiceLocatorInterface  $sl,  $name,  $requestedName)  {                  return  preg_match("/Table$/",  $requestedName);          }            public  function  createServiceWithName(ServiceLocatorInterface  $sl,  $name,  $requestedName)  {                  $adapter  =  $sl-­‐>get('ZendDbAdapterAdapter');                  $tableName  =  str_replace('Table',  '',  $requestedName);                  $tableName  =  strtolower($tableName);                    return  new  TableGateway($tableName,  $adapter);          }   }  
  30. 30. Initializers •  Code  that  needs  to  run  ajer  an  object  is  created   •  Really  helpful  for  when  lots  of  objects  need  addiNonal  objects  (like   loggers)  all  across  the  applicaNon   ZendCon  2015   30  
  31. 31. In ZF2 ZendCon  2015   31   return  [          ’initalizers'  =>  [                  ’JobServiceJobServiceAwareInitializer’          ]   ]  
  32. 32. ZendCon  2015   32   <?php     namespace  JobService;     use  ZendServiceManagerInitializerInterface;   use  ZendServiceManagerServiceLocatorAwareInterface;   use  ZendServiceManagerServiceLocatorInterface;     class  JobServiceAwareInitializer  implements  InitializerInterface   {          public  function  initialize($instance,  ServiceLocatorInterface  $serviceLocator)          {                  if  (!$instance  instanceof  JobServiceAwareInterface)  {                          return  null;                  }                    /**  @var  JobServiceJobService  $jobService  */                  $jobService  =  $serviceLocator-­‐>get('JobService');                    $instance-­‐>setJobService($jobService);          }   }    
  33. 33. Delegators •  They  are  actually  decorators  for  objects  that  don’t  exist   •  They  are  like  iniNalizers  that  only  run  on  a  specific  key   •  Allow  your  applicaNon  to  tweak  or  modify  3rd  party  objects  without   having  to  extend  them   ZendCon  2015   33  
  34. 34. In ZF2 ZendCon  2015   34   return  [          ’delgators'  =>  [                  ’OtherVendorAccountAccountService’  =>  [                          ‘MyProjectAccountAccountServiceDelegator’,                  ]          ]   ]  
  35. 35. ZendCon  2015   35   <?php     namespace  MyProject;     use  ZendServiceManagerDelegatorFactoryInterface;   use  ZendServiceManagerServiceLocatorInterface;     class  AccountServiceDelegator  implements  DelegatorFactoryInterface  {          public  function  createDelegatorWithName(ServiceLocatorInterface  $sl,  $name,  $requestedName,   $callback)  {                  $originalService  =  $callback();                  $accountService  =  new  MyProjectAccountAccountService($originalService);                                    return  $accountService;          }   }  
  36. 36. Aliases •  Just  another  name  for  some  other  key  in  the  service  manager   ZendCon  2015   36  
  37. 37. In ZF2 ZendCon  2015   37   return  [          ’aliases'  =>  [                  ’MyProjectAccountOldAccountService’  =>  ‘MyProjectAccountNewAccountService’,          ]   ]  
  38. 38. Bad Practices ZendCon  2015   38  
  39. 39. Lots of Initializers •  IniNalizers  run  ajer  every  object  is  created   •  30  iniNalizers  *  50  objects  created  at  runNme  =    1500  invocaNons   •  Look  at  using  Factories  instead  to  inject  things  into  your  objects   •  Look  at  using  Delegators   ZendCon  2015   39  
  40. 40. Functions as Factories •  The  Factory  system  will  actually  take  any  invokable  thing  as  a  factory   •  That  means  you  can  use  closures  and  anonymous  classes   ZendCon  2015   40  
  41. 41. ZendCon  2015   41   return  [          'factories'  =>  array(                  'CategoryService'  =>  function($sm)  {                          $categoryService  =  new  CategoryService();                          $categoryService-­‐>setCategoryTable($sm-­‐>get('CategoryTable'));                          return  $categoryService;                  },                  'CategoryTable'  =>  function($sm)  {                          $tableGateway  =  $sm-­‐>get('CategoryTableGateway');                          $table  =  new  CategoryTable($tableGateway);                          return  $table;                  },                  'CategoryTableGateway'  =>  function($sm)  {                          $dbAdapter  =  $sm-­‐>get('ZendDbAdapterAdapter');                          $resultSetPrototype  =  new  ResultSet();                          $resultSetPrototype-­‐>setArrayObjectPrototype(new  Category());                          return  new  TableGateway('category',  $dbAdapter,  null,  $resultSetPrototype);                  },   ]  
  42. 42. Functions as Factories •  This  makes  the  config  uncachable,  so  there  are  performance  issues   ZendCon  2015   42  
  43. 43. Questions? ZendCon  2015   43  
  44. 44. Thank You! hBp://ctankersley.com   chris@ctankersley.com   @dragonmantank     hBp://joind.in/talk/view/15534   ZendCon  2015   44  

×