D8: DI, DIC, Services

Photo by Carli Jeen on Unsplash

The root!

What is a good framework

for you?

  • easy to use

  • secure

  • extendable

  • stable

extendable

great DX?

+

Gonna make this?

Dependency Injection

class Laptop {

  public function getStatusInfo() {
    $cpu = new Intel();
    $cpu->getStatus();
  }

}

$laptop = new Laptop();
$laptop->getStatusInfo();
class Laptop {
  
  protected $cpu;

  public function __construct(Intell $cpu) {
    $this->cpu = $cpu;
  }

  public function getStatusInfo() {
    $this->cpu->getStatus();
  }

}

$cpu    = new Intel();
$laptop = new Laptop($cpu);

$laptop->getStatusInfo();
interface CpuInterface {

  public function getStatus();

}

class Laptop {
  
  protected $cpu;

  public function __construct(CpuInterface $cpu) {
    $this->cpu = $cpu;
  }

  public function getStatusInfo() {
    $this->cpu->getStatus();
  }

}

$cpu    = new Intel();
$laptop = new Laptop($cpu);

$laptop->getStatusInfo();

👍

DI

DI Container

// Who should do this? I don't want!
// I want to get somewhere this objects.
$cpu    = new Intel();
$laptop = new Laptop($cpu);

...

// And finally...
$laptop->getStatusInfo();

DIC

?

// Somewhere in framework code.
$dic = new DIC();
$dic->register('cpu_provider', function() {
    return new Intel();
});
$dic->register('laptop_provider', function() use($dic) {
    return new Laptop($dic->resolve('cpu_provider'));
});

...

// Somewhere in my code
$laptop = $dic->resolve('laptop_provider');
$laptop->getStatusInfo();

🚀

DIC

The main goal of IoC and DI is to remove dependencies of an application. This makes the system more decoupled and maintainable.

💡

What is a service?

Services

for procedural guys

require_once MY_SUPER_USEFUL_LIBRARY . '/payment.paypal.api.php';

$payment = payment_paypal_get_api();
$payment->connect();

in AngularJS

  • provides method to keep data across the lifetime of the app
  • provides method to communicate data across the controllers in a consistent way
  • used to organize and share data and functions across the application

😀

in Drupal

In Drupal 8 speak, a service is any object managed by the services container.

 

Drupal 8 introduces the concept of services to decouple reusable functionality and makes these services pluggable and replaceable by registering them with a service container.

core.services.yml

Service

twig:
  class: Drupal\Core\Template\TwigEnvironment
  arguments: ['@app.root', ... , '%twig_extension_hash%', ... ]
  tags:
    - { name: service_collector, tag: 'twig.extension', call: addExtension }

twig.extension:
  class: Drupal\Core\Template\TwigExtension
  arguments: ['@renderer', ...]
  tags:
    - { name: twig.extension, priority: 100 }

machine name

implementation

dependencies

filters

config variable

service

definitions

static

*.services.yml

user.auth:
  class: Drupal\user\UserAuth
  arguments: ['@entity.manager', '@password']

YML

CLASS

define

alter

namespace Drupal\my_module;

class MyModuleServiceProvider implements ServiceModifierInterface {  
  
  public function alter(ContainerBuilder $container) {
    $definition = $container->getDefinition('language_manager');
    $definition->setClass('Drupal\my_module\LanguageManager')
      ->addArgument(new Reference('config.factory'))
  }  
}

programmatic

programmatic

namespace Drupal\my_module;

class MyModuleServiceProvider implements ServiceProviderInterface {
  
  public function register(ContainerBuilder $container) {
    if ($this->isMultilingual()) {
      $container->register(
        'mymodule_request_subscriber', 
        'Drupal\my_module\EventSubscriber\LanguageRequestSubscriber'
      )
      ->addTag('event_subscriber')
      ->addArgument(new Reference('language_manager'))
    }
  }
  
}

service

usage

define dependencies

services:
  local_translator.user_skills:
    class: Drupal\local_translator\Services\LocalTranslatorUserSkills
    arguments: ['@current_user', '@config.factory']

inject dependencies in code

class TranslationStatus extends Boolean implements ContainerFactoryPluginInterface {
  
  public function __construct(array $configuration, $plugin_definition, LangManagerInterface $manager) {
    parent::__construct($configuration, $plugin_definition);
    $this->languageManager = $manager;
  }

  public static function create(ContainerInterface $container, array $configuration, $plugin_definition) {
    return new static(
      $configuration, $plugin_id, $plugin_definition,
      $container->get('language_manager')
    );
  }

}
$container->get('language_manager')

problem

solution

result

Links

https://www.codeproject.com/Articles/592372/Dependency-Injection-DI-vs-Inversion-of-Control-IO

https://pimple.symfony.com

https://github.com/rdlowrey/Auryn

Founder @

Co- Founder @

Vladyslav Moyseenko, a.k.a vlad.dancer

&

D8 School: Services, DI, DIC

By Vlad Moyseenko

D8 School: Services, DI, DIC

  • 561