Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
759 views
in Technique[技术] by (71.8m points)

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

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 Slims Container to a class you've written yourself.

However, the OP has asked if it's possible to get Slim to Dependency Inject ALL their classes.

I'm also interested in knowing if there's a way to do this since it seems to be anything but DRY if you have to pass the container to every class that you want to use it.

As an example, if I want to use one of Slim's functions (such as doing a redirect, in one of my own classes) I cannot use this as per the documentation:

$res->withStatus(302)->withHeader('Location', 'your-new-uri');

Because $res (the response object) is not within the scope of my class, unless I inject/pass it.

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.

In frameworks like CakePHP you can use the 'AppController' to globally do stuff like this, i.e. define things once, and make it available in ALL your classes. Does Slim not provide this functionality? If not, that's a serious drawback, IMO.


Edit - I'm adding this from one of the comments I've made to try and explain the issue further:

If you look at the First Application Tutorial - http://slimframework.com/docs/tutorial/first-app.html - they are adding a PDO database connection to the container.

Let's say I have 100 separate classes in a sub-directory (the example has a ../classes/ directory) and autoload them in index.php using spl_autoload_register(). The container is NOT available in any of those classes.

If I had to pass something 100 separate times, each time I use one of my classes, just to get a PDO connection (and that's just one example) then that makes the code very repetetive, i.e. not DRY.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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. :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...