Dependency Injection in Slim Framework - passing Container into your own classes

前端 未结 2 1973
悲&欢浪女
悲&欢浪女 2020-12-18 08:25

I\'ve already commented on this thread but it seems to be dead so I\'m opening a new one: Dependency Injection Slim Framework 3

The post above explains how pass Slim

相关标签:
2条回答
  • 2020-12-18 08:49

    Slim comes with Pimple by default. Some developers argue (and I tend to agree with them) that Pimple is not a dependency injection container, but a service locator, since it doesn't resolve dependencies on its own, you need to register them.

    Slim 3 works with any dependency manager that implements Container interop interface, which PHP-DI does.

    Go for this package. This is what I'm using for my projects and it's simply amazing, because of autowiring. To put it simply, PHP-DI reads constructor of the class and understands what needs to be injected, son you don't have to register dependencies as you would with Pimple.

    Sometimes I think (hope?) that PHP-DI will replace Pimple as Slim's default DI container, because it's simply more advanced.

    Here's how you do with Pimple:

    <?php
    namespace Controllers;
    
    class UsersController
    {
        // Inject Container in controller (which is bad, actually)
        public function __construct(ContainerInterface $container)
        {
            // grab instance from container
            $this->repository = $container['userRepository'];
        }
    
        // Handler of a route
        public function getAllUsers($request, $response)
        {
            $user = $this->repository->getAllUsers();
            return $response->withJson($users);
        }
    }
    

    Here's the same controller with PHP-DI:

    <?php
    namespace Controllers;
    
    class UsersController
    {
        // Declare your dependencies in constructor:
        // PHP-DI will find the classes and inject them automatically
        public function __construct(UserRepository $repository)
        {
            $this->repository = $repository;
        }
    
        // Handler of a route
        public function getAllUsers($request, $response)
        {
            $user = $this->repository->getAllUsers();
            return $response->withJson($users);
        }
    }
    

    The problem with this is, if I have say 100 classes, do I have to pass (or inject) the container 100 times? That seems really, really tedious.

    If you use Slim bundled with PHP-DI, the problem is solved autmatically with autowiring. :)

    0 讨论(0)
  • 2020-12-18 09:01

    The simplest way to do this is like so:

    index.php

    $app->get('/mytest', '\TestController:mytest');
    

    TestController.php

    class TestController {
    
        protected $ci;
    
        public function __construct(Slim\Container $ci) {
            //var_dump($ci);
            $this->ci = $ci;
        }
    
        public function mytest() {
            $sql = ''; // e.g. SQL query
            $stmt = $this->ci->db->prepare($sql);
        }
    }
    

    I'm not sure if this is the "correct" way of doing it, but what happens is that the constructor of TestController receives the container as the first argument. This is mentioned in their documentation: http://www.slimframework.com/docs/objects/router.html#container-resolution

    So when you're using a function like TestController::mytest() it has access to anything in the container, such as the PDO Database instance you set up in index.php (if following their First Application example tutorial).

    As I say, I'm not sure if that's the "right" way of doing it, but it works.

    If you uncomment the var_dump($ci) line in you'll see the Slim Container object.

    If anyone has any feedback on this please comment as I'd be interested in knowing.

    0 讨论(0)
提交回复
热议问题