2. Real World Dependency Injection
About me
Stephan Hochdörfer, bitExpert AG
Department Manager Research Labs
enjoying PHP since 1999
S.Hochdoerfer@bitExpert.de
@shochdoerfer
14. Real World Dependency Injection
„new“ is evil!
<?php
class DeletePage extends Mvc_Action_AAction {
private $pageManager;
public function __construct() {
$this->pageManager = new PageManager();
}
protected function execute(Mvc_Request $request) {
$this->pageManager->delete(
(int) $request->get('pageId')
);
}
}
15. Real World Dependency Injection
„new“ is evil!
<?php
class DeletePage extends Mvc_Action_AAction {
private $pageManager;
public function __construct(PageManager $pm) {
$this->pageManager = $pm;
}
protected function execute(Mvc_Request $request) {
$this->pageManager->delete(
(int) $request->get('pageId')
);
}
}
16. Real World Dependency Injection
"High-level modules should not
depend on low-level modules.
Both should depend on
abstractions."
Robert C. Martin
33. Real World Dependency Injection
Annotation based wiring
<?php
class MySampleService implements IMySampleService {
private $sampleDao;
/**
* @Inject
*/
public function __construct(ISampleDao $sampleDao)
{
$this->sampleDao = $sampleDao;
}
}
34. Real World Dependency Injection
Annotation based wiring
<?php
class MySampleService implements IMySampleService {
private $sampleDao;
/**
* @Inject
* @Named('TheSampleDao')
*/
public function __construct(ISampleDao $sampleDao)
{
$this->sampleDao = $sampleDao;
}
}
40. Real World Dependency Injection
Unittesting made easy
<?php
require_once 'PHPUnit/Framework.php';
class ServiceTest extends PHPUnit_Framework_TestCase {
public function testSampleService() {
// set up dependencies
$sampleDao = $this->getMock('ISampleDao');
$service = new MySampleService($sampleDao);
// run test case
$return = $service->doWork();
// check assertions
$this->assertTrue($return);
}
}
42. Real World Dependency Injection
One class, multiple configurations
Page Exporter
Page Exporter
Released / /Published
Released Published Workingcopy
Workingcopy
Pages
Pages Pages
Pages
43. Real World Dependency Injection
One class, multiple configurations
<?php
abstract class PageExporter {
protected function setPageDao(IPageDao $pageDao) {
$this->pageDao = $pageDao;
}
}
44. Real World Dependency Injection
One class, multiple configurations
<?php
abstract class PageExporter {
protected function setPageDao(IPageDao $pageDao) {
$this->pageDao = $pageDao;
}
}
Remember:
The contract!
45. Real World Dependency Injection
One class, multiple configurations
<?php
class PublishedPageExporter extends PageExporter {
public function __construct() {
$this->setPageDao(new PublishedPageDao());
}
}
class WorkingCopyPageExporter extends PageExporter {
public function __construct() {
$this->setPageDao(new WorkingCopyPageDao());
}
}
46. Real World Dependency Injection
One class, multiple configurations
"Only deleted code is good code!"
Oliver Gierke
47. Real World Dependency Injection
One class, multiple configurations
<?php
class PageExporter {
public function __construct(IPageDao $pageDao) {
$this->pageDao = $pageDao;
}
}
48. Real World Dependency Injection
One class, multiple configurations
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
<bean id="ExportLive" class="PageExporter">
<constructor-arg ref="PublishedPageDao" />
</bean>
<bean id="ExportWorking" class="PageExporter">
<constructor-arg ref="WorkingCopyPageDao" />
</bean>
</beans>
49. Real World Dependency Injection
One class, multiple configurations
<?php
// create ApplicationContext instance
$ctx = new ApplicationContext();
// retrieve live exporter
$exporter = $ctx->getBean('ExportLive');
// retrieve working copy exporter
$exporter = $ctx->getBean('ExportWorking');
51. Real World Dependency Injection
One class, multiple configurations II
http://editor.loc/page/[id]/headline/
http://editor.loc/page/[id]/content/
http://editor.loc/page/[id]/teaser/
52. Real World Dependency Injection
One class, multiple configurations II
<?php
class EditPart extends Mvc_Action_AFormAction {
private $pagePartsManager;
private $type;
public function __construct(IPagePartsManager $pm) {
$this->pagePartsManager = $pm;
}
public function setType($ptype) {
$this->type = (int) $type;
}
protected function process(Bo_ABo $formBackObj) {
}
}
53. Real World Dependency Injection
One class, multiple configurations II
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
<bean id="EditHeadline" class="EditPart">
<constructor-arg ref="PagePartDao" />
<property name="Type" const="PType::Headline" />
</bean>
<bean id="EditContent" class="EditPart">
<constructor-arg ref="PagePartDao" />
<property name="Type" const="PType::Content" />
</bean>
</beans>
55. Real World Dependency Injection
Mocking external service access
WS-
WS-
Booking service
Booking service Webservice
Webservice
Connector
Connector
56. Real World Dependency Injection
Mocking external service access
WS-
WS-
Booking service
Booking service Webservice
Webservice
Connector
Connector
Remember:
The contract!
57. Real World Dependency Injection
Mocking external service access
FS-
FS-
Booking service
Booking service Filesystem
Filesystem
Connector
Connector
58. Real World Dependency Injection
Mocking external service access
FS-
FS-
Booking service
Booking service Filesystem
Filesystem
Connector
Connector
fullfills the
contract!
62. Real World Dependency Injection
No framework dependency
<?php
class MySampleService implements IMySampleService {
private $sampleDao;
public function __construct(ISampleDao $sampleDao) {
$this->sampleDao = $sampleDao;
}
public function getSample($sampleId) {
try {
return $this->sampleDao->readById($sampleId);
}
catch(DaoException $exception) {}
}
}