Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Autowiring

Mike Oram
February 12, 2020

 Autowiring

When learning modern PHP frameworks, the term autowiring crops up quite a bit. In this talk we will explore what autowiring is and how its used. We will look at the mechanics of a framework such as DI, Factories and DIC before looking at how autowiring fits in and how it really works.

Mike Oram

February 12, 2020
Tweet

More Decks by Mike Oram

Other Decks in Programming

Transcript

  1. About me Full-stack developer PHP and JavaScript I run Mayden

    Academy Learn new stuff and teach it to people @MPOram
  2. Postcard @MPOram class UserModel { private $db; private $logger; public

    function __construct() { $this->db = new PDO('mysql:host=127...','user','pass'); $this->logger = new Logger('logs/error.log'); } }
  3. Letter & Envelope class UserModel { private PDO $db; private

    Logger $logger; public function __construct(PDO $db, Logger $logger) { $this->db = $db; $this->logger = $logger; } } @MPOram
  4. Without Dependency Injection $userModel = new UserModel(); With Dependency Injection

    $db = new PDO('mysql:host=127...','user','pass'); $logger = new Logger('logs/error.log'); $userModel = new UserModel($db, $logger); @MPOram
  5. Dependency Injection Pros: • Decouples your dependencies - easier to

    switch out objects • Makes code unit testable - mock dependant objects @MPOram
  6. Dependency Injection Pros: • Decouples your dependencies - easier to

    switch out objects • Makes code unit testable - mock dependant objects Cons: • Have to know the class dependencies - more effort, less encapsulation @MPOram
  7. Dependency Injection Pros: • Decouples your dependencies - easier to

    switch out objects • Makes code unit testable - mock dependant objects Cons: • Have to know the class dependencies - more effort, less encapsulation • Learning curve @MPOram
  8. Dependency Injection Pros: • Decouples your dependencies - easier to

    switch out objects • Makes code unit testable - mock dependant objects Cons: • Have to know the class dependencies - more effort, less encapsulation • Learning curve @MPOram
  9. Factories class UserModel { private PDO $db; private Logger $logger;

    public function __construct(PDO $db, Logger $logger) { $this->db = $db; $this->logger = $logger; } } @MPOram
  10. Factories @MPOram function UserModelFactory { $db = new PDO('mysql:host=127...','user','pass'); $logger

    = new Logger('logs/error.log'); $userModel = new UserModel($db, $logger); return $userModel; }
  11. Factories @MPOram function UserModelFactory { $db = new PDO('mysql:host=127...','user','pass'); $logger

    = new Logger('logs/error.log'); $userModel = new UserModel($db, $logger); return $userModel; } $userModel = UserModelFactory();
  12. Factories Pros: • Removes the need to know dependencies -

    encapsulation • Reduces code duplication - DRY @MPOram
  13. Factories Pros: • Removes the need to know dependencies -

    encapsulation • Reduces code duplication - DRY Cons: • Breaks dependency injection - Create duplicate instances of a class @MPOram
  14. Factories Pros: • Removes the need to know dependencies -

    encapsulation • Reduces code duplication - DRY Cons: • Breaks dependency injection - Create duplicate instances of a class • Have to know/look if a class has a factory or not @MPOram
  15. Dependency Injection Container @MPOram $container = new \App\Container(); $container['db'] =

    new PDO('mysql:host=127...','user','pass'); $container['Logger'] = new Logger('logs/error.log');
  16. Dependency Injection Container @MPOram $container = new \App\Container(); $container['db'] =

    new PDO('mysql:host=127...','user','pass'); $container['Logger'] = new Logger('logs/error.log'); $container['UserModel'] = function ($container) { $db = $container->get('db'); $logger = $container->get('logger'); $userModel = new UserModel($db, $logger); return $userModel; };
  17. Dependency Injection Container @MPOram $container = new \App\Container(); $container['db'] =

    new PDO('mysql:host=127...','user','pass'); $container['Logger'] = new Logger('logs/error.log'); $container['UserModel'] = new UserModelFactory();
  18. Dependency Injection Container @MPOram $container = new \App\Container(); $container['db'] =

    new PDO('mysql:host=127...','user','pass'); $container['Logger'] = new Logger('logs/error.log'); $container['UserModel'] = new UserModelFactory(); // elsewhere in your application $userModel = $container->get('UserModel');
  19. Dependency Injection Container Pros: • Removes the need to know

    dependencies - encapsulation • Removes the need to know if a class has a factory @MPOram
  20. Dependency Injection Container Pros: • Removes the need to know

    dependencies - encapsulation • Removes the need to know if a class has a factory • Reduces code duplication - DRY @MPOram
  21. Dependency Injection Container Pros: • Removes the need to know

    dependencies - encapsulation • Removes the need to know if a class has a factory • Reduces code duplication - DRY • Only one instance of each class @MPOram
  22. Dependency Injection Container Pros: • Removes the need to know

    dependencies - encapsulation • Removes the need to know if a class has a factory • Reduces code duplication - DRY • Only one instance of each class • Centralises object creation @MPOram
  23. Dependency Injection Container Pros: • Removes the need to know

    dependencies - encapsulation • Removes the need to know if a class has a factory • Reduces code duplication - DRY • Only one instance of each class • Centralises object creation Cons: • Can be unnecessarily complex @MPOram
  24. Dependency Injection Container Pros: • Removes the need to know

    dependencies - encapsulation • Removes the need to know if a class has a factory • Reduces code duplication - DRY • Only one instance of each class • Centralises object creation Cons: • Can be unnecessarily complex • Requires a lot of code and setup @MPOram
  25. Okay but… what is autowiring?! 1. Dependency Injection 2. Factories

    3. Dependency Injection Containers 4. Autowiring @MPOram
  26. Autowiring @MPOram class UserModel { private PDO $db; private Logger

    $logger; public function __construct(PDO $db, Logger $logger) { $this->db = $db; $this->logger = $logger; } }
  27. class UserModel { private PDO $db; private Logger $logger; public

    function __construct(PDO $db, Logger $logger) { $this->db = $db; $this->logger = $logger; } } Autowiring @MPOram
  28. class UserModel { private PDO $db; private Logger $logger; public

    function __construct(PDO $db, Logger $logger) { $this->db = $db; $this->logger = $logger; } } $userModel = $container->get('UserModel'); Autowiring @MPOram
  29. Autowiring Pros: • No factories • No DIC configuration •

    Easy to use • Multi-stage dependency resolution @MPOram
  30. class UserController { private UserModel $model; public function __construct(UserModel $model)

    { $this->model = $model; } } $userController = $container->get('UserController'); Autowiring @MPOram
  31. $userController = $container->get('UserController'); $db = new PDO('mysql:host=127...','user','pass'); $logger = new

    Logger('logs/error.log'); $userModel = new UserModel($db, $logger); Autowiring @MPOram
  32. $userController = $container->get('UserController'); $db = new PDO('mysql:host=127...','user','pass'); $logger = new

    Logger('logs/error.log'); $userModel = new UserModel($db, $logger); $userController = new UserController($userModel); Autowiring @MPOram
  33. Autowiring Pros: • No factories • No DIC configuration •

    Easy to use • Multi-stage dependency resolution @MPOram
  34. Autowiring Cons: • Black Magic @MPOram Pros: • No factories

    • No DIC configuration • Easy to use • Multi-stage dependency resolution
  35. Autowiring Cons: • Black Magic • Performance (sometimes) @MPOram Pros:

    • No factories • No DIC configuration • Easy to use • Multi-stage dependency resolution
  36. Autowiring - How it works 1. Get list of constructor

    dependencies 2. Get the type hint for each dependency @MPOram
  37. Autowiring - How it works 1. Get list of constructor

    dependencies 2. Get the type hint for each dependency 3. Get an instance of each typehint, either from the DIC or by creating a new instance @MPOram
  38. Autowiring - How it works 1. Get list of constructor

    dependencies 2. Get the type hint for each dependency 3. Get an instance of each typehint, either from the DIC or by creating a new instance 4. Instantiate desired class with its dependencies @MPOram
  39. $reflection = new ReflectionClass('UserModel'); $args = $reflection->getConstructor()->getParameters(); foreach ($args as

    $arg) { $dependencyName = $arg->getClass()->getName(); } ReflectionClass @MPOram
  40. $reflection = new ReflectionClass('UserModel'); $args = $reflection->getConstructor()->getParameters(); $dependencies = [];

    foreach ($args as $arg) { $dependencyName = $arg->getClass()->getName(); $dependencies[] = $container->get($dependencyName); } return new UserModel(...$dependencies); ReflectionClass @MPOram