SlideShare ist ein Scribd-Unternehmen logo
1 von 84
Downloaden Sie, um offline zu lesen
Dependency Injection in Drupal 8
Intro
● Rudimentary understanding of OOP assumed
● Big changes in D8
● Not enough time to explain ALL THE THINGS
but I'll provide a list of resources for a deeper
dive into DI
Agenda
● DI as a design pattern
● DI from a framework perspective
● Symfony-style DI
● DI in Drupal 8
Agenda
● DI as a design pattern
● DI from a framework perspective
● Symfony-style DI
● DI in Drupal 8
Why?
How?
Why Dependency Injection?
Goal: we want to write code
that is...
✔Clutter-free
✔Reusable
✔Testable
Doing It Wrong
1. An example in procedural code
function my_module_func($val1, $val2) {
module_load_include('module_x', 'inc');
$val1 = module_x_process_val($val1);
return $val1 + $val2;
}
function my_module_func($val1, $val2) {
module_load_include('module_x', 'inc');
$val1 = module_x_process_val($val1);
return $val1 + $val2;
}
✗ Clutter-free
✗ Reusable
✗ Testable
Doing It Wrong
1. An example in procedural code
2. An example in Object Oriented code
class Notifier {
private $mailer;
public function __construct() {
$this->mailer = new Mailer();
}
public function notify() {
...
$this->mailer->send($from, $to, $msg);
...
}
}
class Notifier {
private $mailer;
public function __construct() {
$this->mailer = new Mailer('sendmail');
}
public function notify() {
...
$this->mailer->send($from, $to, $msg);
...
}
}
class Notifier {
private $mailer;
public function __construct(Mailer $m) {
$this->mailer = $m;
}
public function notify() {
...
$this->mailer->send($from, $to, $msg);
...
}
}
class Notifier {
private $mailer;
public function __construct(Mailer $m) {
$this->mailer = $m;
}
public function notify() {
...
$this->mailer->send($from, $to, $msg);
...
}
}
$mailer = new Mailer();
$notifier = new Notifier($mailer);
Goal: we want to write code
that is...
✔Clutter-free
✔Reusable
✔Testable
Goal: we want to write code
that is...
✔Clutter-free
✔Reusable
✔Testable
Ignorant
The less your code knows, the more
reusable it is.
class Notifier {
private $mailer;
public function __construct(Mailer $m) {
$this->mailer = $m;
}
public function notify() {
...
$this->mailer->send($from, $to, $msg);
...
}
}
$mailer = new Mailer();
$notifier = new Notifier($mailer);
class Notifier {
private $mailer;
public function
__construct(MailerInterface $m) {
$this->mailer = $m;
}
public function notify() {
...
$this->mailer->send($from, $to, $msg);
...
}
}
$mailer = new SpecialMailer();
$notifier = new Notifier($mailer);
class Notifier {
private $mailer;
public function
__construct(MailerInterface $m) {
$this->mailer = $m;
}
public function notify() {
...
$this->mailer->send($from, $to, $msg);
...
}
}
$mailer = new SpecialMailer();
$notifier = new Notifier($mailer);
Constructor Injection
Dependency Injection
Declaratively express dependencies in the
class definition rather than instantiating them
in the class itself.
Constructor Injection is not
the only form of DI
Setter Injection
class Notifier {
private $mailer;
public function
setMailer(MailerInterface $m) {
$this->mailer = $m;
}
public function notify() {
...
$this->mailer->send($msg);
}
}
$mailer = new Mailer();
$notifier = new Notifier();
$notifier->setMailer($mailer);
class Notifier {
private $mailer;
public function
setMailer(MailerInterface $m) {
$this->mailer = $m;
}
public function notify() {
...
$this->mailer->send($msg);
}
}
$mailer = new Mailer();
$notifier = new Notifier();
$notifier->setMailer($mailer);
Setter Injection
Interface Injection
Like setter injection, except there is an
interface for each dependency's setter
method.
Very verbose
Not very common
Dependency Injection
==
Inversion of Control
“Don't call us,
we'll call you!”
(The Hollywood Principle)
class Notifier {
private $mailer;
public function
__construct(MailerInterface $m) {
$this->mailer = $m;
}
public function notify() {
...
$this->mailer->send($from, $to, $msg);
...
}
}
$mailer = new Mailer();
$notifier = new Notifier($mailer);
class Notifier {
private $mailer;
public function
__construct(MailerInterface $m) {
$this->mailer = $m;
}
public function notify() {
...
$this->mailer->send($from, $to, $msg);
...
}
}
$mailer = new Mailer();
$notifier = new Notifier($mailer);?
Where does injection happen?
Where does injection happen?
➔ Manual injection
➔ Use a factory
➔ Use a container / injector
Using DI in a Framework
Dependency Injector
==
Dependency Injection Container (DIC)
==
IoC Container
==
Service Container
The Service Container
➔ Assumes responsibility for constructing
object graphs (i.e. instantiating your
classes with their dependencies)
➔ Uses configuration data to know how to
do this
➔ Allows infrastructure logic to be kept
separate from application logic
Objects as Services
A service is an object that provides some kind of
globally useful functionality
Examples of Services
➔ Cache Backend
➔ Logger
➔ Mailer
➔ URL Generator
Examples of Non-Services
➔ Product
➔ Blog post
➔ Email message
Source: Dependency Injection by Dhanji R. Prasanna, published by Manning
Source: Dependency Injection by Dhanji R. Prasanna, published by Manning
Sample configuration
<services...>
<service id=”notifier” class=”Notifier”>
<constructor-arg ref=”emailer” />
</service>
<service id=”emailer” class=”Mailer”>
<constructor-arg ref=”spell_checker” />
</service>
<service id=”spell_checker”
class=”SpellChecker” />
</services>
How does it work?
➔ Service keys map to service definitions
➔ Definitions specify which class to
instantiate and what its dependencies
are
➔ Dependencies are specified as
references to other services (using
service keys)
➔ Keys are unique per object graph
➔ $container->getService('some_service')
Service Keys
Each key corresponds to a unique object graph, e.g.
'english_mailer' corresponds to
new Mailer(new EnglishSpellchecker())
'french_mailer' corresponds to
new Mailer(new FrenchSpellchecker())
Container Configuration
➔ Via an API
➔ Using XML
➔ Using YAML
Scope
The scope of a service is the context under which
the service key refers to the same instance.
Common Scopes
Container scope (aka Singleton scope)
The container returns the same instance every time
a client requests that service
Prototype scope (aka no scope)
The container returns a new instance every time a
client requests that service
Request scope
Every request for the service within the context of
an HTTP request will get the same instance.
Service Locator vs. DI
class SomeClass {
public function __construct(Locator $sl) {
$this->myDep = $sl->get('some_service');
}
}
In DI, calls like
$container->get('some_service')
should only happen at the entry point to the
application
Source: Dependency Injection by Dhanji R. Prasanna, published by Manning
Source: Dependency Injection by Dhanji R. Prasanna, published by Manning
Service Locator
Service Locator
Getting wired in is not just about
configuration, it's about how the
application works with the
container.
Symfony's Dependency Injection
Component
Symfony's DI Component
➔ Service keys are strings, e.g. 'some_service'
➔ Service definitions, in addition to specifying
which class to instantiate and what
constructor arguments to pass in, allow you to
specify additional methods to call on the
object after instantiation
Symfony's DI Component
➔ Default scope: container
➔ Can be configured in PHP, XML or YAML
➔ Can be “compiled” down to plain PHP
Some Symfony Terminology
“Compiling” the container
It's too expensive to parse configuration on
every request.
Parse once and put the result into a PHP class
that hardcodes a method for each service.
“Compiling” the container
Class service_container extends Container {
/**
* Gets the 'example' service.
*/
protected function getExampleService()
{
return $this->services['example'] = new
SomeNamespaceSomeClass();
}
}
“Synthetic” Services
A synthetic service is one that is not instantiated
by the container – the container just gets told
about it so it can then treat it as a service when
anything has a dependency on it.
Bundles
Bundles are Symfony's answer to plugins or
modules, i.e. prepackaged sets of functionality
implementing a particular feature, e.g. a blog.
Bundles need to be able to interact with the
container so they provide a class implementing
the BundleInterace which allows them to do so.
Compiler passes
Compiler passes give you an opportunity to
manipulate other service definitions that have
been registered with the service container.
Use them to:
● Specify a different class for a given service id
● Process “tagged” services
Tagged Services
You can add tags to your services when you
define them. This flags them for some kind of
special processing (in a compiler pass).
For example, this mechanism is used to register
event subscribers (services tagged with
'event_subscriber') to Symfony's event
dispatcher
Symfony's Event Dispatcher
plays an important role in
container wiring
Symfony's Event Dispatcher
➔ Dispatcher dispatches events such as
Kernel::Request
➔ Can be used to dispatch any kind of custom
event
➔ Event listeners are registered to the
dispatcher and notified when an event fires
➔ Event subscribers are classes that provide
multiple event listeners for different events
Symfony's Event Dispatcher
➔ A compiler pass registers all subscribers to
the dispatcher, using their service IDs
➔ The dispatcher holds a reference to the
service container
➔ Can therefore instantiate “subscriber
services” with their dependencies
class RegisterKernelListenersPass implements
CompilerPassInterface {
public function process(ContainerBuilder $container) {
$definition = $container
->getDefinition('event_dispatcher');
$services = $container
->findTaggedServiceIds('event_subscriber');
foreach ($services as $id => $attributes) {
$definition->addMethodCall('addSubscriberService',
array($id, $class));
}
}
}
A compiler pass iterates over the
tagged services
class CoreBundle extends Bundle {
public function build(ContainerBuilder $container)
{
...
// Compiler pass for event subscribers.
$container->addCompilerPass(new
RegisterKernelListenersPass());
...
}
}
Register the compiler pass
Dependency Injection in Drupal 8
Some D8 Services
➔ The default DB connection ('database')
➔ The module handler ('module_handler')
➔ The HTTP request object ('request')
Services:
database:
class: DrupalCoreDatabaseConnection
factory_class: DrupalCoreDatabaseDatabase
factory_method: getConnection
arguments: [default]
path.alias_whitelist:
class: DrupalCorePathAliasWhitelist
tags:
- { name: needs_destruction }
language_manager:
class: DrupalCoreLanguageLanguageManager
path.alias_manager:
class: DrupalCorePathAliasManager
arguments: ['@database',
'@path.alias_whitelist', '@language_manager']
class AliasManager implements AliasManagerInterface {
...
public function __construct(Connection $connection,
AliasWhitelist $whitelist, LanguageManager
$language_manager) {
$this->connection = $connection;
$this->languageManager = $language_manager;
$this->whitelist = $whitelist;
}
...
}
AliasManager's Constructor
2 ways you can use core's
services
1. From procedural code, using a helper
(essentially a service locator)
2. Write OO code and get wired into the
container
Drupal's Application Flow
Get wired in as an event
subscriber
Services:
...
path_subscriber:
class: DrupalCoreEventSubscriberPathSubscriber
tags:
- { name: event_subscriber }
...
Tagged Services
How to get your controller
wired in?
Controllers as Services?
➔ Controllers have dependencies on services
➔ Whether they should be directly wired into
the container is a hotly debated topic in the
Symfony community
➔ Recommended way in D8 is not to make
controllers themselves services but to
implement a special interface that has a
factory method which accepts the container
➔ See book module for an example!
Don't inject the container!
Ever.
(Unless you absolutely must)
Where does it all happen?
➔ The Drupal Kernel:
core/lib/Drupal/Core/DrupalKernel.php
➔ Services are defined in:
core/core.services.yml
➔ Compiler passes get added in:
core/lib/Drupal/Core/CoreBundle.php
➔ Compiler pass classes live here:
core/lib/Drupal/Core/DependencyInjection/
Compiler/...
What about modules?
➔ Services are defined in:
mymodule/mymodule.services.yml
➔ Compiler passes get added in:
mymodule/lib/Drupal/mymodule/MymoduleB
undle.php
➔ All classes, including compiler pass classes,
must live in
mymodule/lib/Drupal/mymodule/
Easy testability with DI and
PHPUnit
PHPUnit Awesomeness
// Create a language manager stub.
$language_manager = $this
->getMock('DrupalCoreLanguageLanguageManager');
$language_manager->expects($this->any())
->method('getLanguage')
->will($this->returnValue((object) array(
'langcode' => 'en',
'name' => 'English')));
PHPUnit Awesomeness
// Create an alias manager stub.
$alias_manager = $this
->getMockBuilder('DrupalCorePathAliasManager')
->disableOriginalConstructor()
->getMock();
$alias_manager->expects($this->any())
->method('getSystemPath')
->will($this->returnValueMap(array(
'foo' => 'user/1',
'bar' => 'node/1',
)));
Resources
These slides and a list of resources on DI and
its use in Symfony and Drupal are available at
http://katbailey.github.io/
Questions?

Weitere ähnliche Inhalte

Was ist angesagt?

the communicative approach
the communicative approachthe communicative approach
the communicative approachnurul fitriana
 
Content Based Instruction
Content Based InstructionContent Based Instruction
Content Based InstructionMandy Cheng 92
 
Grammar translation method presentation
Grammar translation method presentationGrammar translation method presentation
Grammar translation method presentationyenniferpks77
 
teaching writing in L2
teaching writing in L2teaching writing in L2
teaching writing in L2Arash Akbari
 
Teaching English to Young Learners.
Teaching English to Young Learners.Teaching English to Young Learners.
Teaching English to Young Learners.massoud oussama
 
Content based instruction
Content based instructionContent based instruction
Content based instructionedaunsun
 
Direct method By Katherine Camacho
Direct method By Katherine CamachoDirect method By Katherine Camacho
Direct method By Katherine CamachoKatherine Beatriz
 
Direct teaching presentation rc
Direct teaching presentation rcDirect teaching presentation rc
Direct teaching presentation rcRuth Camorlinga
 
C# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoringC# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoringEyob Lube
 
21st Century Skills in the Foreign Language Classroom
21st Century Skills in the Foreign Language Classroom21st Century Skills in the Foreign Language Classroom
21st Century Skills in the Foreign Language ClassroomPip Cleaves
 
Applied linguistics "An informed approach"
Applied linguistics "An informed approach"Applied linguistics "An informed approach"
Applied linguistics "An informed approach"Kum Visal
 
Learners' roles in the different teaching approaches and methods
Learners' roles in the different teaching approaches and methodsLearners' roles in the different teaching approaches and methods
Learners' roles in the different teaching approaches and methodsAbla BEN BELLAL
 
ELT Methodology; The Development and Choice Dilemma
ELT Methodology; The Development and Choice DilemmaELT Methodology; The Development and Choice Dilemma
ELT Methodology; The Development and Choice DilemmaAbdelmjid Seghir
 
Total physical response
Total physical responseTotal physical response
Total physical responseRaj Wali Khan
 
The grammar translation method
The grammar translation methodThe grammar translation method
The grammar translation methodffffunes
 
Approaches and methods in language teaching
Approaches and methods in language teachingApproaches and methods in language teaching
Approaches and methods in language teachingOderayQuijada
 
Toward a post method pedagogy
Toward a post method pedagogyToward a post method pedagogy
Toward a post method pedagogySamaneh Shafeie
 
TEFL (Direct Method, PPP, CLL)
TEFL (Direct Method, PPP, CLL)TEFL (Direct Method, PPP, CLL)
TEFL (Direct Method, PPP, CLL)Widya Alfiani
 

Was ist angesagt? (20)

the communicative approach
the communicative approachthe communicative approach
the communicative approach
 
Content Based Instruction
Content Based InstructionContent Based Instruction
Content Based Instruction
 
Grammar translation method presentation
Grammar translation method presentationGrammar translation method presentation
Grammar translation method presentation
 
teaching writing in L2
teaching writing in L2teaching writing in L2
teaching writing in L2
 
Teaching English to Young Learners.
Teaching English to Young Learners.Teaching English to Young Learners.
Teaching English to Young Learners.
 
Content based instruction
Content based instructionContent based instruction
Content based instruction
 
Direct method By Katherine Camacho
Direct method By Katherine CamachoDirect method By Katherine Camacho
Direct method By Katherine Camacho
 
Direct teaching presentation rc
Direct teaching presentation rcDirect teaching presentation rc
Direct teaching presentation rc
 
C# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoringC# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoring
 
21st Century Skills in the Foreign Language Classroom
21st Century Skills in the Foreign Language Classroom21st Century Skills in the Foreign Language Classroom
21st Century Skills in the Foreign Language Classroom
 
Applied linguistics "An informed approach"
Applied linguistics "An informed approach"Applied linguistics "An informed approach"
Applied linguistics "An informed approach"
 
What is B-learning
What is B-learningWhat is B-learning
What is B-learning
 
Learners' roles in the different teaching approaches and methods
Learners' roles in the different teaching approaches and methodsLearners' roles in the different teaching approaches and methods
Learners' roles in the different teaching approaches and methods
 
ELT Methodology; The Development and Choice Dilemma
ELT Methodology; The Development and Choice DilemmaELT Methodology; The Development and Choice Dilemma
ELT Methodology; The Development and Choice Dilemma
 
Methods of teaching english
Methods of teaching englishMethods of teaching english
Methods of teaching english
 
Total physical response
Total physical responseTotal physical response
Total physical response
 
The grammar translation method
The grammar translation methodThe grammar translation method
The grammar translation method
 
Approaches and methods in language teaching
Approaches and methods in language teachingApproaches and methods in language teaching
Approaches and methods in language teaching
 
Toward a post method pedagogy
Toward a post method pedagogyToward a post method pedagogy
Toward a post method pedagogy
 
TEFL (Direct Method, PPP, CLL)
TEFL (Direct Method, PPP, CLL)TEFL (Direct Method, PPP, CLL)
TEFL (Direct Method, PPP, CLL)
 

Ähnlich wie Dependency Injection in Drupal 8

Dependency injection in CakePHP
Dependency injection in CakePHPDependency injection in CakePHP
Dependency injection in CakePHPmarkstory
 
Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8Alexei Gorobets
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the TrenchesJonathan Wage
 
Dependency injection in Drupal 8 : DrupalCon NOLA
Dependency injection in Drupal 8 : DrupalCon NOLADependency injection in Drupal 8 : DrupalCon NOLA
Dependency injection in Drupal 8 : DrupalCon NOLAAshwini Kumar
 
Dependency Injection, Zend Framework and Symfony Container
Dependency Injection, Zend Framework and Symfony ContainerDependency Injection, Zend Framework and Symfony Container
Dependency Injection, Zend Framework and Symfony ContainerDiego Lewin
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodeSWIFTotter Solutions
 
Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenchesLukas Smith
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016Kacper Gunia
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf Conference
 
Dependency Injection and Pimple
Dependency Injection and PimpleDependency Injection and Pimple
Dependency Injection and PimpleDQNEO
 
A Series of Fortunate Events - Symfony Camp Sweden 2014
A Series of Fortunate Events - Symfony Camp Sweden 2014A Series of Fortunate Events - Symfony Camp Sweden 2014
A Series of Fortunate Events - Symfony Camp Sweden 2014Matthias Noback
 
Into the ZF2 Service Manager
Into the ZF2 Service ManagerInto the ZF2 Service Manager
Into the ZF2 Service ManagerChris Tankersley
 
A Series of Fortunate Events - PHP Benelux Conference 2015
A Series of Fortunate Events - PHP Benelux Conference 2015A Series of Fortunate Events - PHP Benelux Conference 2015
A Series of Fortunate Events - PHP Benelux Conference 2015Matthias Noback
 
Angular presentation
Angular presentationAngular presentation
Angular presentationMatus Szabo
 
Introduction to Domain driven design (LaravelBA #5)
Introduction to Domain driven design (LaravelBA #5)Introduction to Domain driven design (LaravelBA #5)
Introduction to Domain driven design (LaravelBA #5)guiwoda
 
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...go_oh
 

Ähnlich wie Dependency Injection in Drupal 8 (20)

Dependency injection in CakePHP
Dependency injection in CakePHPDependency injection in CakePHP
Dependency injection in CakePHP
 
Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the Trenches
 
Dependency injection in Drupal 8 : DrupalCon NOLA
Dependency injection in Drupal 8 : DrupalCon NOLADependency injection in Drupal 8 : DrupalCon NOLA
Dependency injection in Drupal 8 : DrupalCon NOLA
 
Dependency Injection, Zend Framework and Symfony Container
Dependency Injection, Zend Framework and Symfony ContainerDependency Injection, Zend Framework and Symfony Container
Dependency Injection, Zend Framework and Symfony Container
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better Code
 
Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenches
 
The IoC Hydra
The IoC HydraThe IoC Hydra
The IoC Hydra
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
 
Dependency Injection and Pimple
Dependency Injection and PimpleDependency Injection and Pimple
Dependency Injection and Pimple
 
A Series of Fortunate Events - Symfony Camp Sweden 2014
A Series of Fortunate Events - Symfony Camp Sweden 2014A Series of Fortunate Events - Symfony Camp Sweden 2014
A Series of Fortunate Events - Symfony Camp Sweden 2014
 
Into the ZF2 Service Manager
Into the ZF2 Service ManagerInto the ZF2 Service Manager
Into the ZF2 Service Manager
 
AngularJS
AngularJSAngularJS
AngularJS
 
A Series of Fortunate Events - PHP Benelux Conference 2015
A Series of Fortunate Events - PHP Benelux Conference 2015A Series of Fortunate Events - PHP Benelux Conference 2015
A Series of Fortunate Events - PHP Benelux Conference 2015
 
Angular presentation
Angular presentationAngular presentation
Angular presentation
 
Introduction to Domain driven design (LaravelBA #5)
Introduction to Domain driven design (LaravelBA #5)Introduction to Domain driven design (LaravelBA #5)
Introduction to Domain driven design (LaravelBA #5)
 
Design patterns in PHP
Design patterns in PHPDesign patterns in PHP
Design patterns in PHP
 
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...
 

Kürzlich hochgeladen

Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 

Kürzlich hochgeladen (20)

Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 

Dependency Injection in Drupal 8

  • 2. Intro ● Rudimentary understanding of OOP assumed ● Big changes in D8 ● Not enough time to explain ALL THE THINGS but I'll provide a list of resources for a deeper dive into DI
  • 3. Agenda ● DI as a design pattern ● DI from a framework perspective ● Symfony-style DI ● DI in Drupal 8
  • 4. Agenda ● DI as a design pattern ● DI from a framework perspective ● Symfony-style DI ● DI in Drupal 8 Why? How?
  • 6. Goal: we want to write code that is... ✔Clutter-free ✔Reusable ✔Testable
  • 7. Doing It Wrong 1. An example in procedural code
  • 8. function my_module_func($val1, $val2) { module_load_include('module_x', 'inc'); $val1 = module_x_process_val($val1); return $val1 + $val2; }
  • 9. function my_module_func($val1, $val2) { module_load_include('module_x', 'inc'); $val1 = module_x_process_val($val1); return $val1 + $val2; } ✗ Clutter-free ✗ Reusable ✗ Testable
  • 10. Doing It Wrong 1. An example in procedural code 2. An example in Object Oriented code
  • 11. class Notifier { private $mailer; public function __construct() { $this->mailer = new Mailer(); } public function notify() { ... $this->mailer->send($from, $to, $msg); ... } }
  • 12. class Notifier { private $mailer; public function __construct() { $this->mailer = new Mailer('sendmail'); } public function notify() { ... $this->mailer->send($from, $to, $msg); ... } }
  • 13. class Notifier { private $mailer; public function __construct(Mailer $m) { $this->mailer = $m; } public function notify() { ... $this->mailer->send($from, $to, $msg); ... } }
  • 14. class Notifier { private $mailer; public function __construct(Mailer $m) { $this->mailer = $m; } public function notify() { ... $this->mailer->send($from, $to, $msg); ... } } $mailer = new Mailer(); $notifier = new Notifier($mailer);
  • 15. Goal: we want to write code that is... ✔Clutter-free ✔Reusable ✔Testable
  • 16. Goal: we want to write code that is... ✔Clutter-free ✔Reusable ✔Testable Ignorant
  • 17. The less your code knows, the more reusable it is.
  • 18. class Notifier { private $mailer; public function __construct(Mailer $m) { $this->mailer = $m; } public function notify() { ... $this->mailer->send($from, $to, $msg); ... } } $mailer = new Mailer(); $notifier = new Notifier($mailer);
  • 19. class Notifier { private $mailer; public function __construct(MailerInterface $m) { $this->mailer = $m; } public function notify() { ... $this->mailer->send($from, $to, $msg); ... } } $mailer = new SpecialMailer(); $notifier = new Notifier($mailer);
  • 20. class Notifier { private $mailer; public function __construct(MailerInterface $m) { $this->mailer = $m; } public function notify() { ... $this->mailer->send($from, $to, $msg); ... } } $mailer = new SpecialMailer(); $notifier = new Notifier($mailer); Constructor Injection
  • 21. Dependency Injection Declaratively express dependencies in the class definition rather than instantiating them in the class itself.
  • 22. Constructor Injection is not the only form of DI
  • 24. class Notifier { private $mailer; public function setMailer(MailerInterface $m) { $this->mailer = $m; } public function notify() { ... $this->mailer->send($msg); } } $mailer = new Mailer(); $notifier = new Notifier(); $notifier->setMailer($mailer);
  • 25. class Notifier { private $mailer; public function setMailer(MailerInterface $m) { $this->mailer = $m; } public function notify() { ... $this->mailer->send($msg); } } $mailer = new Mailer(); $notifier = new Notifier(); $notifier->setMailer($mailer); Setter Injection
  • 26. Interface Injection Like setter injection, except there is an interface for each dependency's setter method. Very verbose Not very common
  • 28.
  • 29.
  • 30. “Don't call us, we'll call you!” (The Hollywood Principle)
  • 31. class Notifier { private $mailer; public function __construct(MailerInterface $m) { $this->mailer = $m; } public function notify() { ... $this->mailer->send($from, $to, $msg); ... } } $mailer = new Mailer(); $notifier = new Notifier($mailer);
  • 32. class Notifier { private $mailer; public function __construct(MailerInterface $m) { $this->mailer = $m; } public function notify() { ... $this->mailer->send($from, $to, $msg); ... } } $mailer = new Mailer(); $notifier = new Notifier($mailer);?
  • 34. Where does injection happen? ➔ Manual injection ➔ Use a factory ➔ Use a container / injector
  • 35. Using DI in a Framework Dependency Injector == Dependency Injection Container (DIC) == IoC Container == Service Container
  • 36. The Service Container ➔ Assumes responsibility for constructing object graphs (i.e. instantiating your classes with their dependencies) ➔ Uses configuration data to know how to do this ➔ Allows infrastructure logic to be kept separate from application logic
  • 37. Objects as Services A service is an object that provides some kind of globally useful functionality
  • 38. Examples of Services ➔ Cache Backend ➔ Logger ➔ Mailer ➔ URL Generator
  • 39. Examples of Non-Services ➔ Product ➔ Blog post ➔ Email message
  • 40. Source: Dependency Injection by Dhanji R. Prasanna, published by Manning
  • 41. Source: Dependency Injection by Dhanji R. Prasanna, published by Manning
  • 42. Sample configuration <services...> <service id=”notifier” class=”Notifier”> <constructor-arg ref=”emailer” /> </service> <service id=”emailer” class=”Mailer”> <constructor-arg ref=”spell_checker” /> </service> <service id=”spell_checker” class=”SpellChecker” /> </services>
  • 43. How does it work? ➔ Service keys map to service definitions ➔ Definitions specify which class to instantiate and what its dependencies are ➔ Dependencies are specified as references to other services (using service keys) ➔ Keys are unique per object graph ➔ $container->getService('some_service')
  • 44. Service Keys Each key corresponds to a unique object graph, e.g. 'english_mailer' corresponds to new Mailer(new EnglishSpellchecker()) 'french_mailer' corresponds to new Mailer(new FrenchSpellchecker())
  • 45. Container Configuration ➔ Via an API ➔ Using XML ➔ Using YAML
  • 46. Scope The scope of a service is the context under which the service key refers to the same instance.
  • 47. Common Scopes Container scope (aka Singleton scope) The container returns the same instance every time a client requests that service Prototype scope (aka no scope) The container returns a new instance every time a client requests that service Request scope Every request for the service within the context of an HTTP request will get the same instance.
  • 48. Service Locator vs. DI class SomeClass { public function __construct(Locator $sl) { $this->myDep = $sl->get('some_service'); } } In DI, calls like $container->get('some_service') should only happen at the entry point to the application
  • 49. Source: Dependency Injection by Dhanji R. Prasanna, published by Manning
  • 50. Source: Dependency Injection by Dhanji R. Prasanna, published by Manning Service Locator Service Locator
  • 51. Getting wired in is not just about configuration, it's about how the application works with the container.
  • 53. Symfony's DI Component ➔ Service keys are strings, e.g. 'some_service' ➔ Service definitions, in addition to specifying which class to instantiate and what constructor arguments to pass in, allow you to specify additional methods to call on the object after instantiation
  • 54. Symfony's DI Component ➔ Default scope: container ➔ Can be configured in PHP, XML or YAML ➔ Can be “compiled” down to plain PHP
  • 56. “Compiling” the container It's too expensive to parse configuration on every request. Parse once and put the result into a PHP class that hardcodes a method for each service.
  • 57. “Compiling” the container Class service_container extends Container { /** * Gets the 'example' service. */ protected function getExampleService() { return $this->services['example'] = new SomeNamespaceSomeClass(); } }
  • 58. “Synthetic” Services A synthetic service is one that is not instantiated by the container – the container just gets told about it so it can then treat it as a service when anything has a dependency on it.
  • 59. Bundles Bundles are Symfony's answer to plugins or modules, i.e. prepackaged sets of functionality implementing a particular feature, e.g. a blog. Bundles need to be able to interact with the container so they provide a class implementing the BundleInterace which allows them to do so.
  • 60. Compiler passes Compiler passes give you an opportunity to manipulate other service definitions that have been registered with the service container. Use them to: ● Specify a different class for a given service id ● Process “tagged” services
  • 61. Tagged Services You can add tags to your services when you define them. This flags them for some kind of special processing (in a compiler pass). For example, this mechanism is used to register event subscribers (services tagged with 'event_subscriber') to Symfony's event dispatcher
  • 62. Symfony's Event Dispatcher plays an important role in container wiring
  • 63. Symfony's Event Dispatcher ➔ Dispatcher dispatches events such as Kernel::Request ➔ Can be used to dispatch any kind of custom event ➔ Event listeners are registered to the dispatcher and notified when an event fires ➔ Event subscribers are classes that provide multiple event listeners for different events
  • 64. Symfony's Event Dispatcher ➔ A compiler pass registers all subscribers to the dispatcher, using their service IDs ➔ The dispatcher holds a reference to the service container ➔ Can therefore instantiate “subscriber services” with their dependencies
  • 65. class RegisterKernelListenersPass implements CompilerPassInterface { public function process(ContainerBuilder $container) { $definition = $container ->getDefinition('event_dispatcher'); $services = $container ->findTaggedServiceIds('event_subscriber'); foreach ($services as $id => $attributes) { $definition->addMethodCall('addSubscriberService', array($id, $class)); } } } A compiler pass iterates over the tagged services
  • 66. class CoreBundle extends Bundle { public function build(ContainerBuilder $container) { ... // Compiler pass for event subscribers. $container->addCompilerPass(new RegisterKernelListenersPass()); ... } } Register the compiler pass
  • 68. Some D8 Services ➔ The default DB connection ('database') ➔ The module handler ('module_handler') ➔ The HTTP request object ('request')
  • 69. Services: database: class: DrupalCoreDatabaseConnection factory_class: DrupalCoreDatabaseDatabase factory_method: getConnection arguments: [default] path.alias_whitelist: class: DrupalCorePathAliasWhitelist tags: - { name: needs_destruction } language_manager: class: DrupalCoreLanguageLanguageManager path.alias_manager: class: DrupalCorePathAliasManager arguments: ['@database', '@path.alias_whitelist', '@language_manager']
  • 70. class AliasManager implements AliasManagerInterface { ... public function __construct(Connection $connection, AliasWhitelist $whitelist, LanguageManager $language_manager) { $this->connection = $connection; $this->languageManager = $language_manager; $this->whitelist = $whitelist; } ... } AliasManager's Constructor
  • 71. 2 ways you can use core's services 1. From procedural code, using a helper (essentially a service locator) 2. Write OO code and get wired into the container
  • 73. Get wired in as an event subscriber
  • 75. How to get your controller wired in?
  • 76. Controllers as Services? ➔ Controllers have dependencies on services ➔ Whether they should be directly wired into the container is a hotly debated topic in the Symfony community ➔ Recommended way in D8 is not to make controllers themselves services but to implement a special interface that has a factory method which accepts the container ➔ See book module for an example!
  • 77. Don't inject the container! Ever. (Unless you absolutely must)
  • 78. Where does it all happen? ➔ The Drupal Kernel: core/lib/Drupal/Core/DrupalKernel.php ➔ Services are defined in: core/core.services.yml ➔ Compiler passes get added in: core/lib/Drupal/Core/CoreBundle.php ➔ Compiler pass classes live here: core/lib/Drupal/Core/DependencyInjection/ Compiler/...
  • 79. What about modules? ➔ Services are defined in: mymodule/mymodule.services.yml ➔ Compiler passes get added in: mymodule/lib/Drupal/mymodule/MymoduleB undle.php ➔ All classes, including compiler pass classes, must live in mymodule/lib/Drupal/mymodule/
  • 80. Easy testability with DI and PHPUnit
  • 81. PHPUnit Awesomeness // Create a language manager stub. $language_manager = $this ->getMock('DrupalCoreLanguageLanguageManager'); $language_manager->expects($this->any()) ->method('getLanguage') ->will($this->returnValue((object) array( 'langcode' => 'en', 'name' => 'English')));
  • 82. PHPUnit Awesomeness // Create an alias manager stub. $alias_manager = $this ->getMockBuilder('DrupalCorePathAliasManager') ->disableOriginalConstructor() ->getMock(); $alias_manager->expects($this->any()) ->method('getSystemPath') ->will($this->returnValueMap(array( 'foo' => 'user/1', 'bar' => 'node/1', )));
  • 83. Resources These slides and a list of resources on DI and its use in Symfony and Drupal are available at http://katbailey.github.io/