08448380779 Call Girls In Friends Colony Women Seeking Men
Real World Dependency Injection - phpugffm13
1.
2. Real World Dependency Injection
Über mich
Stephan Hochdörfer
Head of IT der bitExpert AG, Mannheim
PHP`ler seit 1999
S.Hochdoerfer@bitExpert.de
@shochdoerfer
9. Real World Dependency Injection
Sind Dependencies schlecht?
Fixe Dependencies sind schlecht!
10.
11.
12.
13.
14.
15. 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')
);
}
}
16. 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')
);
}
}
17. Real World Dependency Injection
"High-level modules should not
depend on low-level modules.
Both should depend on
abstractions."
Robert C. Martin
18.
19. Real World Dependency Injection
„new“ is evil!
<?php
class DeletePage extends Mvc_Action_AAction {
private $pageManager;
public function __construct(IPageManager $pm) {
$this->pageManager = $pm;
}
protected function execute(Mvc_Request $request) {
$this->pageManager->delete(
(int) $request->get('pageId')
);
}
}
44. Real World Dependency Injection
Unittesting einfach gemacht
<?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);
}
}
46. Real World Dependency Injection
Eine Klasse, mehrfache Ausprägung
Page Exporter
Page Exporter
Released / /Published
Released Published Workingcopy
Workingcopy
Pages
Pages Pages
Pages
47. Real World Dependency Injection
Eine Klasse, mehrfache Ausprägung
<?php
abstract class PageExporter {
protected function setPageDao(IPageDao $pageDao) {
$this->pageDao = $pageDao;
}
}
48. Real World Dependency Injection
Eine Klasse, mehrfache Ausprägung
<?php
abstract class PageExporter {
protected function setPageDao(IPageDao $pageDao) {
$this->pageDao = $pageDao;
}
}
Zur Erinnerung:
Der Vertrag!
49. Real World Dependency Injection
Eine Klasse, mehrfache Ausprägung
<?php
class PublishedPageExporter extends PageExporter {
public function __construct() {
$this->setPageDao(new PublishedPageDao());
}
}
class WorkingCopyPageExporter extends PageExporter {
public function __construct() {
$this->setPageDao(new WorkingCopyPageDao());
}
}
50. Real World Dependency Injection
Eine Klasse, mehrfache Ausprägung
"Only deleted code is good code!"
Oliver Gierke
51. Real World Dependency Injection
Eine Klasse, mehrfache Ausprägung
<?php
class PageExporter {
public function __construct(IPageDao $pageDao) {
$this->pageDao = $pageDao;
}
}
52. Real World Dependency Injection
Eine Klasse, mehrfache Ausprägung
<?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>
53. Real World Dependency Injection
Eine Klasse, mehrfache Ausprägung
<?php
// create ApplicationContext instance
$ctx = new ApplicationContext();
// retrieve live exporter
$exporter = $ctx->getBean('ExportLive');
// retrieve working copy exporter
$exporter = $ctx->getBean('ExportWorking');
55. Real World Dependency Injection
Eine Klasse, mehrfache Ausprägung II
http://editor.loc/page/[id]/headline/
http://editor.loc/page/[id]/content/
http://editor.loc/page/[id]/teaser/
56. Real World Dependency Injection
Eine Klasse, mehrfache Ausprägung 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) {
}
}
57. Real World Dependency Injection
Eine Klasse, mehrfache Ausprägung 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>
59. Real World Dependency Injection
Externe Services mocken
WS-
WS-
Bookingmanager
Bookingmanager Webservice
Webservice
Konnektor
Konnektor
60. Real World Dependency Injection
Externe Services mocken
WS-
WS-
Bookingmanager
Bookingmanager Webservice
Webservice
Konnektor
Konnektor
Zur Erinnerung:
Der Vertrag!
61. Real World Dependency Injection
Externe Services mocken
FS-
FS-
Bookingmanager
Bookingmanager Filesystem
Filesystem
Konnektor
Konnektor
62. Real World Dependency Injection
Externe Services mocken
FS-
FS-
Bookingmanager
Bookingmanager Filesystem
Filesystem
Konnektor
Konnektor
erfüllt den
Vertrag!
66. Real World Dependency Injection
Keine Framework Abhängigkeit
<?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) {}
}
}
69. Real World Dependency Injection
Pimple – Erste Schritte
<?php
class TalkService {
public function __construct() {
}
public function getTalks() {
}
}
70. Real World Dependency Injection
Pimple – Erste Schritte
<?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'];
71. Real World Dependency Injection
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() {
}
}
72. Real World Dependency Injection
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'];
73. Real World Dependency Injection
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() {
}
}
74. Real World Dependency Injection
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'];
75. Real World Dependency Injection
Pimple – Allgemeines
<?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'];
77. Real World Dependency Injection
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() {
}
}
78. Real World Dependency Injection
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');
79.
80. Real World Dependency Injection
ZendDi – Erste Schritte
<?php
namespace Acme;
class TalkService {
public function __construct() {
}
public function getTalks() {
}
}
81. Real World Dependency Injection
ZendDi – Erste Schritte
<?php
$di = new ZendDiDi();
$service = $di->get('AcmeTalkService');
$service->getTalks();
82. Real World Dependency Injection
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() {
}
}
83. Real World Dependency Injection
ZendDi – Constructor Injection
<?php
$di = new ZendDiDi();
$service = $di->get('AcmeTalkService');
$service->getTalks();
84. Real World Dependency Injection
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() {
}
}
86. Real World Dependency Injection
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() {
}
}
87. Real World Dependency Injection
ZendDi – Interface Injection
<?php
$di = new ZendDiDi();
$service = $di->get('AcmeTalkService');
$service->getTalks();
88. Real World Dependency Injection
ZendDi – Grundsätzliches
<?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
89. Real World Dependency Injection
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);
90. Real World Dependency Injection
ZendDi – Builder Definition
<?php
// add to Di
$defList = new ZendDiDefinitionList($builder);
$di = new ZendDiDi($defList);
$service = $di->get('AcmeTalkService');
var_dump($service);
93. Real World Dependency Injection
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();
}
}
94. Real World Dependency Injection
Symfony2 – Konfigurationsdatei
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>