Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Dependency 
Injection 
in Drupal 8 
Greg Szczotka 
Drupal Camp Wrocław 
19.10.2014
About me 
Greg Szczotka @greg606 
● Lead Developer @ Creaticon 
● angielski-online.pl (Joomla) 
● PHP trainer @ Quali
Drupal 8, welcome to OO!
Why change is hard? 
“Object-oriented design is about managing dependencies. It is a set of coding 
techniques that arrang...
“Because well designed objects have a single 
responsibility, their very nature requires that they 
collaborate to accompl...
Dependency Injection 
"Dependency Injection" is a 25-dollar 
term for a 5-cent concept.
Depenency Injection - Definition 
« Dependency Injection is where components are given 
their dependencies through their c...
Why DI ? 
Goal: we want to write code that is... 
✔ Clutter-free 
✔ Reusable 
✔ Testable
An injection is the passing of a dependency (a service) to a 
dependent object (a client). 
The service is made part of th...
What are dependencies? 
● framework 
● third party libraries 
● database 
● filesystem 
● email 
● web services 
● system ...
Before DI 
class A 
{ 
public function a1() { 
$b = new B(); 
$b->b1(); 
} 
}
class Flashcard 
{ 
private $db; 
public function __construct() 
{ 
hard to customize 
$this->db = new new MysqlConnection...
Types of DI 
- constructor injection 
- setter injection 
- interface injection 
- property injection
DI - Constructor Injection 
class Flashcard 
{ 
private $db; 
public function __construct(MySqlConnection $db) 
{ 
$this->...
DI - Setter Injection 
class Flashcard 
{ 
private $db; 
public setDb(MySqlConnection $db) 
{ 
$this->db = $db; 
} 
}
Dependency injection is a software design 
pattern that implements inversion of control and 
allows a program design to fo...
SOLID 
● Single responsibility, 
● Open-closed, 
● Liskov substitution, 
● Interface segregation, 
● Dependency inversion
Depend on abstractions, not on concretions.
Dependency Inversion Principle 
A. High-level modules should not depend on low-level modules. 
Both should depend on abstr...
class Flashcard 
{ 
private $db; 
public function __construct(MySqlConnection $db) 
{ 
$this->db = $db; 
} 
}
interface ConnectionInterface { 
public function connect(); 
} 
class DbConnection implements ConnectionInterface { 
publi...
Dependency Injection 
== 
Inversion of Control
Inversion of Control 
A design in which custom-written portions of a computer program receive the 
flow of control from a ...
IoC = Hollywood Principle 
"don't call us, we'll call you." 
Instead of your program running the system, the system runs y...
Inversion of Control - Why? 
● To decouple the execution of a task from implementation. 
● To focus a module on the task i...
IoC - implementations 
● factory pattern 
● service locator pattern 
● dependency injection 
● contextualized lookup 
● te...
The less your code knows, the 
more reusable it is.
DI - Problem 
$transport = new 
Zend_Mail_Transport_Smtp('smtp.gmail.com', array( 
'auth' => 'login', 
'username' => 'foo'...
Dependency Injection Container 
A Dependency Injection Container is an object that 
knows how to instantiate and configure...
How does it work? 
➔ Service keys map to service definitions 
➔ Definitions specify which class to instantiate and what it...
Service Container 
➔ Assumes responsibility for constructing object graphs 
(i.e. instantiating your classes with their de...
What is Service? 
A service is any PHP class that performs an action. 
A service is an object that provides some kind of 
...
Examples of Services 
➔ Cache Backend 
➔ Logger 
➔ Mailer 
➔ URL Generator
Examples of NOT Services 
➔ Product 
➔ Blog post 
➔ Email message
Symfony DI Component 
The DependencyInjection component allows you to standardize and 
centralize the way objects are cons...
Symfony DI Component 
● Default scope: container 
● Can be configured in PHP, XML or YAML 
● Can be “compiled” down to pla...
SDIC - Compiling the container 
It's too expensive to parse configuration on 
every request. 
Parse once and put the resul...
SDIC - Compiling the container 
serialization.json: 
class: DrupalComponentSerializationJson 
class service_container exte...
SDIC - Compiling the container 
public function getStateSevice() 
{ return $this->services['state'] = 
new DrupalCoreState...
Some D8 Services 
➔ The default DB connection ('database') 
➔ The module handler ('module_handler') 
➔ The HTTP request ob...
D8 Core Services 
CoreServiceProvider.php and core.services.yml 
language_manager: 
class: DrupalCoreLanguageLanguageManag...
Don't inject the container! 
Ever. 
(Unless you absolutely must)
Service Definition 
module_name.services.yml 
services: 
demo.demo_service: 
class: DrupaldemoDemoService
Service Definition - Arguments 
module_handler: 
class: DrupalCoreExtensionModuleHandler 
arguments: ['%container.modules%...
Service Definition - Calls 
class_resolver: 
class: DrupalCoreDependencyInjectionClassResolver 
calls: 
- [setContainer, [...
Service Definition - Factory 
database: 
class: DrupalCoreDatabaseConnection 
factory_class: DrupalCoreDatabaseDatabase 
f...
Service Definition - Factory Service 
cache.default: 
class: DrupalCoreCacheCacheBackendInterface 
tags: 
- { name: cache....
Service Definition - Alias 
twig.loader: 
alias: twig.loader.filesystem
Service Definition - Abstract/Parent 
default_plugin_manager: 
abstract: true 
arguments: ['@container.namespaces', '@cach...
Service Definition - Public 
config.storage.active: 
class: DrupalCoreConfigDatabaseStorage 
arguments: ['@database', 'con...
D8 - how to get service? 
● Drupal::getContainer()->get('url_generator') 
● Drupal::service('url_generator') 
● Drupal::ur...
D8 - Service Implementation 
namespace Drupaldemo; 
class DemoService { 
protected $demo_value; 
public function __constru...
D8 - Controller 
class DemoController extends ControllerBase { 
public function demo() { return array( 
'#markup' => t('He...
D8 - Controller 
class DemoController extends ControllerBase { 
protected $demoService; 
public function __construct($demo...
D8 - DI for a form 
class ExampleForm extends FormBase { 
public function __construct(AccountInterface $account) { 
$this-...
D8 - Altering existing services, providing dynamic services 
namespace Drupalmy_module;use DrupalCoreDependencyInjection 
...
Service tags 
services: 
foo.twig.extension: 
class: DcwrocHelloBundleExtensionFooExtension 
tags: 
- { name: twig.extensi...
D8 Service Tags 
access_check 
authentication_provider 
breadcrumb_builder 
cache.bin 
cache.context 
config.factory.overr...
Resources 
● Inversion of Control Containers and the Dependency 
Injection pattern 
● Symfony Service Container 
● The Dep...
Dependency injection Drupal Camp Wrocław 2014
Dependency injection Drupal Camp Wrocław 2014
Dependency injection Drupal Camp Wrocław 2014
Upcoming SlideShare
Loading in …5
×

Dependency injection Drupal Camp Wrocław 2014

489 views

Published on

Dependency injection Drupal Camp Wrocław 2014

Published in: Software
  • Be the first to comment

Dependency injection Drupal Camp Wrocław 2014

  1. 1. Dependency Injection in Drupal 8 Greg Szczotka Drupal Camp Wrocław 19.10.2014
  2. 2. About me Greg Szczotka @greg606 ● Lead Developer @ Creaticon ● angielski-online.pl (Joomla) ● PHP trainer @ Quali
  3. 3. Drupal 8, welcome to OO!
  4. 4. Why change is hard? “Object-oriented design is about managing dependencies. It is a set of coding techniques that arrange dependencies such that objects can tolerate change. In the absence of design, unmanaged dependencies wreak havoc because objects know too much about one another. Changing one object forces change upon its collaborators, which in turn, forces change upon its collaborators, ad infinitum. A seemingly insignificant enhancement can cause damage that radiates outward in overlapping concentric circles, ultimately leaving no code untouched. When objects know too much they have many expectations about the world in which they reside. They’re picky, they need things to be “just so.” These expectations constrain them. The objects resist being reused in different contexts; they are painful to test and susceptible to being duplicated.” Sandi Metz. “Practical Object-Oriented Design in Ruby: An Agile Primer (Jason Arnold's Library).”
  5. 5. “Because well designed objects have a single responsibility, their very nature requires that they collaborate to accomplish complex tasks. This collaboration is powerful and perilous. To collaborate, an object must know something know about others. Knowing creates a dependency. If not managed carefully, these dependencies will strangle your application.” Sandi Metz. “Practical Object-Oriented Design in Ruby: An Agile Primer (Jason Arnold's Library).”
  6. 6. Dependency Injection "Dependency Injection" is a 25-dollar term for a 5-cent concept.
  7. 7. Depenency Injection - Definition « Dependency Injection is where components are given their dependencies through their constructors, methods, or directly into fields. »
  8. 8. Why DI ? Goal: we want to write code that is... ✔ Clutter-free ✔ Reusable ✔ Testable
  9. 9. An injection is the passing of a dependency (a service) to a dependent object (a client). The service is made part of the client's state. Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern.
  10. 10. What are dependencies? ● framework ● third party libraries ● database ● filesystem ● email ● web services ● system resources (Clock) ● configuration ● the new keyword ● static methods ● random
  11. 11. Before DI class A { public function a1() { $b = new B(); $b->b1(); } }
  12. 12. class Flashcard { private $db; public function __construct() { hard to customize $this->db = new new MysqlConnection('flashcards'); } } $flashcard = new Flashcard(); easy to use
  13. 13. Types of DI - constructor injection - setter injection - interface injection - property injection
  14. 14. DI - Constructor Injection class Flashcard { private $db; public function __construct(MySqlConnection $db) { $this->db = $db; } } $db = new MySQLConnection(); $flashcard = new Flashcard($db); slightly more difficult to use
  15. 15. DI - Setter Injection class Flashcard { private $db; public setDb(MySqlConnection $db) { $this->db = $db; } }
  16. 16. Dependency injection is a software design pattern that implements inversion of control and allows a program design to follow the dependency inversion principle.
  17. 17. SOLID ● Single responsibility, ● Open-closed, ● Liskov substitution, ● Interface segregation, ● Dependency inversion
  18. 18. Depend on abstractions, not on concretions.
  19. 19. Dependency Inversion Principle A. High-level modules should not depend on low-level modules. Both should depend on abstractions. B. Abstractions should not depend on details. Details should depend on abstractions.
  20. 20. class Flashcard { private $db; public function __construct(MySqlConnection $db) { $this->db = $db; } }
  21. 21. interface ConnectionInterface { public function connect(); } class DbConnection implements ConnectionInterface { public function connect() { //do something }; }class Flashcard { public function __construct(ConnectionInterface $connection){ $this->connection = $connection; } } $db = new DbConnection(); $flashcard = new Flashcard($db);
  22. 22. Dependency Injection == Inversion of Control
  23. 23. Inversion of Control A design in which custom-written portions of a computer program receive the flow of control from a generic, reusable library. A software architecture with this design inverts control as compared to traditional procedural programming: in traditional programming, the custom code that expresses the purpose of the program calls into reusable libraries to take care of generic tasks, but with inversion of control, it is the reusable code that calls into the custom, or task-specific, code.
  24. 24. IoC = Hollywood Principle "don't call us, we'll call you." Instead of your program running the system, the system runs your program.
  25. 25. Inversion of Control - Why? ● To decouple the execution of a task from implementation. ● To focus a module on the task it is designed for. ● To free modules from assumptions about how other systems do what they do and instead rely on contracts. ● To prevent side effects when replacing a module.
  26. 26. IoC - implementations ● factory pattern ● service locator pattern ● dependency injection ● contextualized lookup ● template method pattern ● strategy pattern
  27. 27. The less your code knows, the more reusable it is.
  28. 28. DI - Problem $transport = new Zend_Mail_Transport_Smtp('smtp.gmail.com', array( 'auth' => 'login', 'username' => 'foo', 'password' => 'bar', 'ssl' => 'ssl', 'port' => 465, )); $mailer = new Zend_Mail(); $mailer->setDefaultTransport($transport);
  29. 29. Dependency Injection Container A Dependency Injection Container is an object that knows how to instantiate and configure objects. And to be able to do its job, it needs to knows about the constructor arguments and the relationships between the objects. These objects are called Services.
  30. 30. 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) ➔ $container->getService('some_service')
  31. 31. 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
  32. 32. What is Service? A service is any PHP class that performs an action. A service is an object that provides some kind of globally useful functionality “A service is an object, registered at the service container under a certain id. ” Matthias Noback. “A Year With Symfony.”
  33. 33. Examples of Services ➔ Cache Backend ➔ Logger ➔ Mailer ➔ URL Generator
  34. 34. Examples of NOT Services ➔ Product ➔ Blog post ➔ Email message
  35. 35. Symfony DI Component The DependencyInjection component allows you to standardize and centralize the way objects are constructed in your application.
  36. 36. Symfony DI Component ● Default scope: container ● Can be configured in PHP, XML or YAML ● Can be “compiled” down to plain PHP
  37. 37. SDIC - 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.
  38. 38. SDIC - Compiling the container serialization.json: class: DrupalComponentSerializationJson class service_container extends Container { public function getSerialization_JsonService() { return $this->services['serialization.json'] = new DrupalComponentSerializationJson(); } }
  39. 39. SDIC - Compiling the container public function getStateSevice() { return $this->services['state'] = new DrupalCoreStateState( $this->get('keyvalue') ); }
  40. 40. Some D8 Services ➔ The default DB connection ('database') ➔ The module handler ('module_handler') ➔ The HTTP request object ('request')
  41. 41. D8 Core Services CoreServiceProvider.php and core.services.yml language_manager: class: DrupalCoreLanguageLanguageManager arguments: ['@language.default'] path.alias_manager: class: DrupalCorePathAliasManager arguments: ['@path.crud', '@path.alias_whitelist', '@language_manager'] string_translation: class: DrupalCoreStringTranslationTranslationManager breadcrumb: class: DrupalCoreBreadcrumbBreadcrumbManager arguments: ['@module_handler']
  42. 42. Don't inject the container! Ever. (Unless you absolutely must)
  43. 43. Service Definition module_name.services.yml services: demo.demo_service: class: DrupaldemoDemoService
  44. 44. Service Definition - Arguments module_handler: class: DrupalCoreExtensionModuleHandler arguments: ['%container.modules%', '@cache.bootstrap']
  45. 45. Service Definition - Calls class_resolver: class: DrupalCoreDependencyInjectionClassResolver calls: - [setContainer, ['@service_container']]
  46. 46. Service Definition - Factory database: class: DrupalCoreDatabaseConnection factory_class: DrupalCoreDatabaseDatabase factory_method: getConnection arguments: [default]
  47. 47. Service Definition - Factory Service cache.default: class: DrupalCoreCacheCacheBackendInterface tags: - { name: cache.bin } factory_method: get factory_service: cache_factory arguments: [default]
  48. 48. Service Definition - Alias twig.loader: alias: twig.loader.filesystem
  49. 49. Service Definition - Abstract/Parent default_plugin_manager: abstract: true arguments: ['@container.namespaces', '@cache.discovery', '@module_handler'] plugin.manager.archiver: class: DrupalCoreArchiverArchiverManager parent: default_plugin_manager
  50. 50. Service Definition - Public config.storage.active: class: DrupalCoreConfigDatabaseStorage arguments: ['@database', 'config'] public: false tags: - { name: backend_overridable }config.storage.file: class: DrupalCoreConfigFileStorage factory_class: DrupalCoreConfigFileStorageFactory factory_method: getActive public: false
  51. 51. D8 - how to get service? ● Drupal::getContainer()->get('url_generator') ● Drupal::service('url_generator') ● Drupal::urlGenerator() please don’t! INJECT LIKE HELL
  52. 52. D8 - Service Implementation namespace Drupaldemo; class DemoService { protected $demo_value; public function __construct() { $this->demo_value = 'Upchuk'; } public function getDemoValue() { return $this- >demo_value; } }
  53. 53. D8 - Controller class DemoController extends ControllerBase { public function demo() { return array( '#markup' => t('Hello @value!', array('@value' => $this- >demoService->getDemoValue())), ); } }
  54. 54. D8 - Controller class DemoController extends ControllerBase { protected $demoService; public function __construct($demoService) { $this->demoService = $demoService; } public static function create(ContainerInterface $container) { return new static( $container->get('demo.demo_service') ); } }
  55. 55. D8 - DI for a form class ExampleForm extends FormBase { public function __construct(AccountInterface $account) { $this->account = $account; } public static function create(ContainerInterface $container) { // Instantiates this form class. return new static( // Load the service required to construct this class. $container->get('current_user') ); } }
  56. 56. D8 - Altering existing services, providing dynamic services namespace Drupalmy_module;use DrupalCoreDependencyInjection ContainerBuilder;use DrupalCoreDependencyInjection ServiceProviderBase;class MyModuleServiceProvider extends ServiceProviderBase { public function alter(ContainerBuilder $container) { // Overrides language_manager class to test domain language negotiation. $definition = $container->getDefinition('language_manager'); $definition->setClass('Drupallanguage_testLanguageTestManager'); } }
  57. 57. Service tags services: foo.twig.extension: class: DcwrocHelloBundleExtensionFooExtension tags: - { name: twig.extension }
  58. 58. D8 Service Tags access_check authentication_provider breadcrumb_builder cache.bin cache.context config.factory.override encoder entity_resolver event_subscriber needs_destruction normalizer paramconverter path_processor_inbound persist plugin_manager_cache_clear route_enhancer route_filter route_processor_outbound string_translator theme_negotiator twig.extension
  59. 59. Resources ● Inversion of Control Containers and the Dependency Injection pattern ● Symfony Service Container ● The DependencyInjection Component ● Services and dependency injection in Drupal 8

×