44
Into the ZF2 Service Manager Chris Tankersley ZendCon 2015 ZendCon 2015 1

Into the ZF2 Service Manager

Embed Size (px)

Citation preview

Page 1: Into the ZF2 Service Manager

Into the ZF2 Service Manager Chris  Tankersley  ZendCon  2015  

ZendCon  2015   1  

Page 2: Into the ZF2 Service Manager

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  

Page 3: Into the ZF2 Service Manager

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  

Page 4: Into the ZF2 Service Manager

ZendCon  2015   4  

Page 5: Into the ZF2 Service Manager

It kind of is…

ZendCon  2015   5  

return  [          'service_manager'  =>  [                  'initializers'  =>  [                          'Job\Service\JobServiceAwareInitializer'                  ],                  'invokables'  =>  [                          'Job\ProcessorListener'  =>  'Job\Processor\ProcessorListener',                          'Job\ServiceAccountListener'  =>  'Job\Service\JobServiceListener’                      ],                  'factories'  =>  [                          'Job\Service'                      =>  'Job\Service\JobServiceFactory',                          'Job\Processor'                  =>  'Job\Processor\ProcessorFactory',                  ]          ]  ]  

Page 6: Into the ZF2 Service Manager

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  

Page 7: Into the ZF2 Service Manager

The Service Manager

ZendCon  2015   7  

Page 8: Into the ZF2 Service Manager

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  

Page 9: Into the ZF2 Service Manager

What can we store in there?

•  Invokables  •  Factories  • Abstract  Factories  • Delegators  •  IniNalizers  • Aliases  

ZendCon  2015   9  

Page 10: Into the ZF2 Service Manager

Standalone

$serviceManager  =  new  Zend\ServiceManager\ServiceManager();  $serviceManager-­‐>setService(‘MyService’,  $myService);    $serviceManager-­‐>has(‘MyService’);  $service  =  $serviceManager-­‐>get(‘MyService’);    

ZendCon  2015   10  

Page 11: Into the ZF2 Service Manager

Built into ZF2 full-stack applications

• Anything  that  is  ServiceLocatorAwareInterface  can  have  it  injected  • Controllers  are  the  most  common  

ZendCon  2015   11  

namespace  Application\Controller;    use  Zend\Mvc\Controller\AbstractActionController;    class  IndexController  extends  AbstractActionController  {          public  function  indexAction()  {                  $model  =  $this-­‐>getServiceLocator()-­‐>get(‘My\Model’);          }  }  

Page 12: Into the ZF2 Service Manager

Stuff we can get from the Service Manager

ZendCon  2015   12  

Page 13: Into the ZF2 Service Manager

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';          }  }  

Page 14: Into the ZF2 Service Manager

In ZF2 return  [  

       'service_manager'  =>  [                  'invokables'  =>  [                          'Job\Processor\ProcessorListener'  =>  'Job\Processor\ProcessorListener',                          'Job\ServiceAccountListener'  =>  'Job\Service\JobServiceListener'                  ],  

       ]  

]  

ZendCon  2015   14  

Page 15: Into the ZF2 Service Manager

Quick Dependency Injection Tutorial

ZendCon  2015   15  

Page 16: Into the ZF2 Service Manager

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  

Page 17: Into the ZF2 Service Manager

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  

Page 18: Into the ZF2 Service Manager

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  

Page 19: Into the ZF2 Service Manager

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  

Page 20: Into the ZF2 Service Manager

Back to the show

ZendCon  2015   20  

Page 21: Into the ZF2 Service Manager

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  

Page 22: Into the ZF2 Service Manager

Why do we need factories?

Dependencies  

ZendCon  2015   22  

Page 23: Into the ZF2 Service Manager

In ZF2

ZendCon  2015   23  

return  [          'service_manager'  =>  [                  ’factories'  =>  [                          'Google\AdWords\AdWordsUserBuilder'  =>  'Google\AdWords\GoogleAdWordsUserBuilderFactory',                  ],          ]  ]  

Page 24: Into the ZF2 Service Manager

ZendCon  2015   24  

namespace  Google\AdWords;    class  GoogleAdWordsUserBuilder  {          public  function  __construct(array  $config)  {                  $this-­‐>config  =  $config;          }  }    

Page 25: Into the ZF2 Service Manager

ZendCon  2015   25  

namespace  Google\AdWords;    use  Zend\ServiceManager\FactoryInterface;  use  Zend\ServiceManager\ServiceLocatorInterface;    class  GoogleAdWordsUserBuilderFactory  implements  FactoryInterface  {          public  function  createService(ServiceLocatorInterface  $service)          {                  $config  =  $service-­‐>get('Config');                  return  new  GoogleAdWordsUserBuilder($config[‘google’]);          }  }    

Page 26: Into the ZF2 Service Manager

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  

Page 27: Into the ZF2 Service Manager

ZendCon  2015   27  

<?php    namespace  MyProject;    use  Zend\Db\TableGateway\TableGateway;  use  Zend\ServiceManager\FactoryInterface;  use  Zend\ServiceManager\ServiceLocatorInterface;    class  ProjectsTableFactory  implements  FactoryInterface  {          public  function  createService(ServiceLocatorInterface  $serviceLocator)  {                  $adapter  =  new  $serviceLocator-­‐>get('Zend\Db\Adapter\Adapter');                  return  new  TableGateway('projects',  $adapter);          }  }    class  CategoriesTableFactory  implements  FactoryInterface  {          public  function  createService(ServiceLocatorInterface  $serviceLocator)  {                  $adapter  =  new  $serviceLocator-­‐>get('Zend\Db\Adapter\Adapter');                  return  new  TableGateway('categories',  $adapter);          }  }  

Page 28: Into the ZF2 Service Manager

In ZF2

ZendCon  2015   28  

return  [          ’abstract_factories'  =>  [                  ’MyProject\TableAbstractFactory’          ]  ]  

Page 29: Into the ZF2 Service Manager

ZendCon  2015   29  

<?php    namespace  MyProject;    use  Zend\Db\TableGateway\TableGateway;  use  Zend\ServiceManager\AbstractFactoryInterface;  use  Zend\ServiceManager\ServiceLocatorInterface;    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('Zend\Db\Adapter\Adapter');                  $tableName  =  str_replace('Table',  '',  $requestedName);                  $tableName  =  strtolower($tableName);                    return  new  TableGateway($tableName,  $adapter);          }  }  

Page 30: Into the ZF2 Service Manager

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  

Page 31: Into the ZF2 Service Manager

In ZF2

ZendCon  2015   31  

return  [          ’initalizers'  =>  [                  ’Job\Service\JobServiceAwareInitializer’          ]  ]  

Page 32: Into the ZF2 Service Manager

ZendCon  2015   32  

<?php    namespace  Job\Service;    use  Zend\ServiceManager\InitializerInterface;  use  Zend\ServiceManager\ServiceLocatorAwareInterface;  use  Zend\ServiceManager\ServiceLocatorInterface;    class  JobServiceAwareInitializer  implements  InitializerInterface  {          public  function  initialize($instance,  ServiceLocatorInterface  $serviceLocator)          {                  if  (!$instance  instanceof  JobServiceAwareInterface)  {                          return  null;                  }                    /**  @var  \Job\Service\JobService  $jobService  */                  $jobService  =  $serviceLocator-­‐>get('Job\Service');                    $instance-­‐>setJobService($jobService);          }  }    

Page 33: Into the ZF2 Service Manager

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  

Page 34: Into the ZF2 Service Manager

In ZF2

ZendCon  2015   34  

return  [          ’delgators'  =>  [                  ’OtherVendor\Account\AccountService’  =>  [                          ‘MyProject\Account\AccountServiceDelegator’,                  ]          ]  ]  

Page 35: Into the ZF2 Service Manager

ZendCon  2015   35  

<?php    namespace  MyProject;    use  Zend\ServiceManager\DelegatorFactoryInterface;  use  Zend\ServiceManager\ServiceLocatorInterface;    class  AccountServiceDelegator  implements  DelegatorFactoryInterface  {          public  function  createDelegatorWithName(ServiceLocatorInterface  $sl,  $name,  $requestedName,  $callback)  {                  $originalService  =  $callback();                  $accountService  =  new  MyProject\Account\AccountService($originalService);                                    return  $accountService;          }  }  

Page 36: Into the ZF2 Service Manager

Aliases

•  Just  another  name  for  some  other  key  in  the  service  manager  

ZendCon  2015   36  

Page 37: Into the ZF2 Service Manager

In ZF2

ZendCon  2015   37  

return  [          ’aliases'  =>  [                  ’MyProject\Account\OldAccountService’  =>  ‘MyProject\Account\NewAccountService’,          ]  ]  

Page 38: Into the ZF2 Service Manager

Bad Practices

ZendCon  2015   38  

Page 39: Into the ZF2 Service Manager

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  

Page 40: Into the ZF2 Service Manager

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  

Page 41: Into the ZF2 Service Manager

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('Zend\Db\Adapter\Adapter');                          $resultSetPrototype  =  new  ResultSet();                          $resultSetPrototype-­‐>setArrayObjectPrototype(new  Category());                          return  new  TableGateway('category',  $dbAdapter,  null,  $resultSetPrototype);                  },  ]  

Page 42: Into the ZF2 Service Manager

Functions as Factories

•  This  makes  the  config  uncachable,  so  there  are  performance  issues  

ZendCon  2015   42  

Page 43: Into the ZF2 Service Manager

Questions?

ZendCon  2015   43  

Page 44: Into the ZF2 Service Manager

Thank You!

hBp://ctankersley.com  [email protected]  

@dragonmantank    

hBp://joind.in/talk/view/15534  

ZendCon  2015   44