The document discusses dependency injection (DI) in PHP. It provides an overview of common DI containers and frameworks used in PHP projects, including Pimple, Bucket, Zend\Di, and Symfony. For each option, it demonstrates basic usage including constructor injection, setter injection, and retrieving services from the container. It also discusses concepts like shared services, configuration via XML, and injecting dependencies via interfaces or properties. The document serves as a high-level introduction to dependency injection in PHP.
2. The state of DI in PHP
About me
Stephan Hochdörfer, bitExpert AG
Department Manager Research Labs
enjoying PHP since 1999
7 years of DI experience (in PHP)
S.Hochdoerfer@bitExpert.de
@shochdoerfer
27. The state of DI in PHP
Pimple – First steps
<?php
class TalkService {
public function __construct() {
}
public function getTalks() {
}
}
28. The state of DI in PHP
Pimple – First steps
<?php
require_once '/path/to/Pimple.php';
require_once '/path/to/TalkService.php';
// create the Container
$container = new Pimple();
// define talkService object in container
$container['talkService'] = function ($c) {
return new TalkService();
};
// instantiate talkService from container
$talkService = $container['talkService'];
29. The state of DI in PHP
Pimple – Constructor Injection
<?php
interface GenericRepository {
public function readTalks();
}
class TalkRepository implements GenericRepository {
public function readTalks() {
}
}
class TalkService {
public function __construct(TalkRepository $repo) {
}
public function getTalks() {
}
}
30. The state of DI in PHP
Pimple – Constructor Injection
<?php
require_once '/path/to/Pimple.php';
require_once '/path/to/TalkService.php';
// create the Container
$container = new Pimple();
// define services in container
$container['talkRepository'] = function ($c) {
return new TalkRepository();
};
$container['talkService'] = function ($c) {
return new TalkService($c['talkRepository']);
};
// instantiate talkService from container
$talkService = $container['talkService'];
31. The state of DI in PHP
Pimple – Setter Injection
<?php
class Logger {
public function doLog($logMsg) {
}
}
class TalkService {
public function __construct(TalkRepository $repo) {
}
public function setLogger(Logger $logger) {
}
public function getTalks() {
}
}
32. The state of DI in PHP
Pimple – Setter Injection
<?php
require_once '/path/to/Pimple.php';
require_once '/path/to/TalkService.php';
// create the Container
$container = new Pimple();
// define services in container
$container['logger'] = function ($c) {
return new Logger();
};
$container['talkRepository'] = function ($c) {
return new TalkRepository();
};
$container['talkService'] = function ($c) {
$service = new TalkService($c['talkRepository']);
$service->setLogger($c['logger']);
return $service;
};
// instantiate talkService from container
$talkService = $container['talkService'];
33. The state of DI in PHP
Pimple – General usage
<?php
require_once '/path/to/Pimple.php';
require_once '/path/to/TalkService.php';
// create the Container
$container = new Pimple();
// define services in container
$container['loggerShared'] = $c->share(function ($c) {
return new Logger();
)};
$container['logger'] = function ($c) {
return new Logger();
};
// instantiate logger from container
$logger = $container['logger'];
// instantiate shared logger from container (same instance!)
$logger2 = $container['loggerShared'];
$logger3 = $container['loggerShared'];
35. The state of DI in PHP
Bucket – Constructor Injection
<?php
interface GenericRepository {
public function readTalks();
}
class TalkRepository implements GenericRepository {
public function readTalks() {
}
}
class TalkService {
public function __construct(TalkRepository $repo) {
}
public function getTalks() {
}
}
36. The state of DI in PHP
Bucket – Constructor Injection
<?php
require_once '/path/to/bucket.inc.php';
require_once '/path/to/TalkService.php';
// create the Container
$container = new bucket_Container();
// instantiate talkService from container
$talkService = $container->create('TalkService');
// instantiate shared instances from container
$talkService2 = $container->get('TalkService');
$talkService3 = $container->get('TalkService');
38. The state of DI in PHP
ZendDi – First steps
<?php
namespace Acme;
class TalkService {
public function __construct() {
}
public function getTalks() {
}
}
39. The state of DI in PHP
ZendDi – First steps
<?php
$di = new ZendDiDi();
$service = $di->get('AcmeTalkService');
$service->getTalks();
40. The state of DI in PHP
ZendDi – Constructor Injection
<?php
namespace Acme;
interface GenericRepository {
public function readTalks();
}
class TalkRepository implements GenericRepository {
public function readTalks() {
}
}
class TalkService {
public function __construct(TalkRepository $repo) {
}
public function getTalks() {
}
}
41. The state of DI in PHP
ZendDi – Constructor Injection
<?php
$di = new ZendDiDi();
$service = $di->get('AcmeTalkService');
$service->getTalks();
42. The state of DI in PHP
ZendDi – Setter Injection
<?php
namespace Acme;
class Logger {
public function doLog($logMsg) {
}
}
class TalkService {
public function __construct(TalkRepository $repo) {
}
public function setLogger(Logger $logger) {
}
public function getTalks() {
}
}
43. The state of DI in PHP
ZendDi – Setter Injection
<?php
$di = new ZendDiDi();
$di->configure(
new ZendDiConfiguration(
array(
'definition' => array(
'class' => array(
'AcmeTalkService' => array(
'setLogger' => array('required' => true)
)
)
)
)
)
);
$service = $di->get('AcmeTalkService');
var_dump($service);
44. The state of DI in PHP
ZendDi – Interface Injection
<?php
namespace Acme;
class Logger {
public function doLog($logMsg) {
}
}
interface LoggerAware {
public function setLogger(Logger $logger);
}
class TalkService implements LoggerAware {
public function __construct(TalkRepository $repo) {
}
public function setLogger(Logger $logger) {
}
public function getTalks() {
}
}
45. The state of DI in PHP
ZendDi – Interface Injection
<?php
$di = new ZendDiDi();
$service = $di->get('AcmeTalkService');
$service->getTalks();
46. The state of DI in PHP
ZendDi – General usage
<?php
$di = new ZendDiDi();
$service = $di->get('AcmeTalkService');
var_dump($service);
$service2 = $di->get('AcmeTalkService');
var_dump($service2); // same instance as $service
$service3 = $di->get(
'AcmeTalkService',
array(
'repo' => new phpbnl12TalkRepository()
)
);
var_dump($service3); // new instance
47. The state of DI in PHP
ZendDi – Builder Definition
<?php
// describe dependency
$dep = new ZendDiDefinitionBuilderPhpClass();
$dep->setName('AcmeTalkRepository');
// describe class
$class = new ZendDiDefinitionBuilderPhpClass();
$class->setName('AcmeTalkService');
// add injection method
$im = new ZendDiDefinitionBuilderInjectionMethod();
$im->setName('__construct');
$im->addParameter('repo', 'AcmeTalkRepository');
$class->addInjectionMethod($im);
// configure builder
$builder = new ZendDiDefinitionBuilderDefinition();
$builder->addClass($dep);
$builder->addClass($class);
48. The state of DI in PHP
ZendDi – Builder Definition
<?php
// add to Di
$defList = new ZendDiDefinitionList($builder);
$di = new ZendDiDi($defList);
$service = $di->get('AcmeTalkService');
var_dump($service);
50. The state of DI in PHP
Symfony2
<?php
namespace AcmeTalkBundleController;
use SymfonyBundleFrameworkBundleControllerController;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
use SensioBundleFrameworkExtraBundleConfigurationTemplate;
class TalkController extends Controller {
/**
* @Route("/", name="_talk")
* @Template()
*/
public function indexAction() {
$service = $this->get('acme.talk.service');
return array();
}
}
51. The state of DI in PHP
Symfony2 – Configuration file
File services.xml in src/Acme/DemoBundle/Resources/config
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">
</container>
52. The state of DI in PHP
Symfony2 – Constructor Injection
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="acme.talk.repo"
class="AcmeTalkBundleServiceTalkRepository" />
<service id="acme.talk.service"
class="AcmeTalkBundleServiceTalkService">
<argument type="service" id="acme.talk.repo" />
</service>
</services>
</container>
53. The state of DI in PHP
Symfony2 – Setter Injection
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="acme.talk.logger"
class="AcmeTalkBundleServiceLogger" />
<service id="acme.talk.repo"
class="AcmeTalkBundleServiceTalkRepository" />
<service id="acme.talk.service"
class="AcmeTalkBundleServiceTalkService">
<argument type="service" id="acme.talk.repo" />
<call method="setLogger">
<argument type="service" id="acme.talk.logger" />
</call>
</service>
</services>
</container>
54. The state of DI in PHP
Symfony2 – Setter Injection (optional)
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="acme.talk.logger"
class="AcmeTalkBundleServiceLogger" />
<service id="acme.talk.repo"
class="AcmeTalkBundleServiceTalkRepository" />
<service id="acme.talk.service"
class="AcmeTalkBundleServiceTalkService">
<argument type="service" id="acme.talk.repo" />
<call method="setLogger">
<argument type="service" id="acme.talk.logger"
on-invalid="ignore" />
</call>
</service>
</services>
</container>
55. The state of DI in PHP
Symfony2 – Property Injection
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="acme.talk.repo"
class="AcmeTalkBundleServiceTalkRepository" />
<service id="acme.talk.service"
class="AcmeTalkBundleServiceTalkService">
<property name="talkRepository" type="service"
id="acme.talk.repo" />
</service>
</services>
</container>
56. The state of DI in PHP
Symfony2 – Interface Injection
Not supported!
57. The state of DI in PHP
Symfony2 – private/public Services
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="acme.talk.logger"
class="AcmeTalkBundleServiceLogger" public="false" />
<service id="acme.talk.repo"
class="AcmeTalkBundleServiceTalkRepository" />
<service id="acme.talk.service"
class="AcmeTalkBundleServiceTalkService">
<argument type="service" id="acme.talk.repo" />
<call method="setLogger">
<argument type="service" id="acme.talk.logger" />
</call>
</service>
</services>
</container>
58. The state of DI in PHP
Symfony2 – Service inheritance
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="acme.talk.serviceparent"
class="AcmeTalkBundleServiceTalkService" abstract="true">
<property name="talkRepository" type="service"
id="acme.talk.repo" />
</service>
<service id="acme.talk.service" parent="acme.talk.serviceparent" />
<service id="acme.talk.service2" parent="acme.talk.serviceparent" />
</services>
</container>
59. The state of DI in PHP
Symfony2 – Service scoping
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="acme.talk.repo"
class="AcmeTalkBundleServiceTalkRepository" />
<service id="acme.talk.service"
class="AcmeTalkBundleServiceTalkService" scope="prototype">
<property name="talkRepository" type="service"
id="acme.talk.repo" />
</service>
</services>
</container>
61. The state of DI in PHP
Flow3 – Constructor Injection
<?php
namespace AcmeDemoController;
use TYPO3FLOW3Annotations as FLOW3;
/**
* @FLOW3Scope("session")
*/
class StandardController extends TYPO3FLOW3MVCControllerActionController {
/**
* @var AcmeDemoServiceTalkServiceInterface
*/
protected $talkService;
public function __construct(
AcmeDemoServiceTalkService $talkService) {
$this->talkService = $talkService;
}
public function indexAction() {
}
}
62. The state of DI in PHP
Flow3 – Setter Injection (manually)
<?php
namespace AcmeDemoController;
use TYPO3FLOW3Annotations as FLOW3;
/**
* @FLOW3Scope("session")
*/
class StandardController extends TYPO3FLOW3MVCControllerActionController {
/**
* @var AcmeDemoServiceTalkServiceInterface
*/
protected $talkService;
public function setTalkService(
AcmeDemoServiceTalkService $talkService) {
$this->talkService = $talkService;
}
public function indexAction() {
}
}
63. The state of DI in PHP
Flow3 – Setter Injection (manually)
File Objects.yaml in Packages/Application/Acme.Demo/Configuration
# @package Acme
AcmeDemoControllerStandardController:
properties:
talkService:
object: AcmeDemoServiceTalkService
64. The state of DI in PHP
Flow3 – Setter Injection (Automagic)
<?php
namespace AcmeDemoController;
use TYPO3FLOW3Annotations as FLOW3;
/**
* @FLOW3Scope("session")
*/
class StandardController extends TYPO3FLOW3MVCControllerActionController {
/**
* @var AcmeDemoServiceTalkServiceInterface
*/
protected $talkService;
public function injectTalkService(
AcmeDemoServiceTalkService $talkService) {
$this->talkService = $talkService;
}
public function indexAction() {
}
}
65. The state of DI in PHP
Flow3 – Setter Injection (Automagic)
<?php
namespace AcmeDemoController;
use TYPO3FLOW3Annotations as FLOW3;
/**
* @FLOW3Scope("session")
*/
class StandardController extends TYPO3FLOW3MVCControllerActionController {
/**
* @var AcmeDemoServiceTalkServiceInterface
*/
protected $talkService;
public function injectSomethingElse(
AcmeDemoServiceTalkService $talkService) {
$this->talkService = $talkService;
}
public function indexAction() {
}
}
66. The state of DI in PHP
Flow3 – Property Injection
<?php
namespace AcmeDemoController;
use TYPO3FLOW3Annotations as FLOW3;
/**
* @FLOW3Scope("session")
*/
class StandardController extends TYPO3FLOW3MVCControllerActionController {
/**
* @var AcmeDemoServiceTalkService
* @FLOW3Inject
*/
protected $talkService;
public function indexAction() {
}
}
67. The state of DI in PHP
Flow3 – Property Injection (with Interface)
<?php
namespace AcmeDemoController;
use TYPO3FLOW3Annotations as FLOW3;
/**
* @FLOW3Scope("session")
*/
class StandardController extends TYPO3FLOW3MVCControllerActionController {
/**
* @var AcmeDemoServiceTalkServiceInterface
* @FLOW3Inject
*/
protected $talkService;
public function indexAction() {
}
}
68. The state of DI in PHP
Flow3 – Property Injection (with Interface)
File Objects.yaml in Packages/Application/Acme.Demo/Configuration
# @package Acme
AcmeDemoServiceTalkServiceInterface:
className: 'AcmeDemoServiceTalkService'
69. The state of DI in PHP
Flow3 – Scoping
<?php
namespace AcmeDemoController;
use TYPO3FLOW3Annotations as FLOW3;
/**
* @FLOW3Scope("session")
*/
class StandardController extends TYPO3FLOW3MVCControllerActionController {
/**
* @var AcmeDemoServiceTalkServiceInterface
* @FLOW3Inject
*/
protected $talkService;
public function indexAction() {
}
}