[ACCEPTED]-How can I use "Dependency Injection" in simple php functions, and should I bother?-parameter-passing

Accepted answer
Score: 79

Dependency injection is a big word for "I 13 have some more parameters in my constructor".

It's 12 what you did before the awfull Singleton 11 wave when you did not like globals :

<?php
class User {
    private $_db;
    function __construct($db) {
        $this->_db = $db;
    }
}

$db   = new Db();
$user = new User($db);

Now, the 10 trick is to use a single class to manage 9 your dependencies, something like that :

class DependencyContainer 
{
    private _instances = array();
    private _params = array();

    public function __construct($params)
    {
        $this->_params = $params;
    }

    public function getDb()
    {
        if (empty($this->_instances['db']) 
            || !is_a($this->_instances['db'], 'PDO')
        ) {
            $this->_instances['db'] = new PDO(
                $this->_params['dsn'],
                $this->_params['dbUser'], 
                $this->_params['dbPwd']
            );
        }
        return $this->_instances['db'];
    }
}

class User
{
    private $_db;
    public function __construct(DependencyContainer $di)
    {
         $this->_db = $di->getDb();
    }
}

$dependencies = new DependencyContainer($someParams);
$user = new User($dependencies);

You 8 must think you just another class and more 7 complexity. But, your user class may need 6 something to log messages like lot of other 5 classes. Just add a getMessageHandler function 4 to your dependency container, and some $this->_messages = $di->getMessageHandler() to 3 your user class. Nothing to change in the 2 rest of your code.

You'll get lot of infos 1 on symfony's doc

Score: 14

Your first example IS dependancy injection, you 5 are injecting the dependency on the database 4 object into the function.

Sarah has said 3 this isn't, but imo it is, I believe she 2 is thinking of dependency injection containers 1 which are the next level up:

http://components.symfony-project.org/dependency-injection/trunk/book/02-Dependency-Injection-Containers

Score: 6

None of your examples look like dependency 20 injection, version one is the closest though. Dependency 19 injection is a technique used in object 18 oriented programming, where the constructor 17 of an object has arguments for the service 16 objects it needs, and those service objects 15 are passed in by the creator of the instance 14 (which could be a factory, a test, or a 13 dependency injection framework).

To get around 12 your 'always passing the connection object' problem 11 you may want to consider the template pattern. The 10 template pattern is basically an abstract 9 base class with the common part of a repeated 8 code block, and abstract methods to allow 7 for the variation between the instances 6 of those repeated code blocks. Basically 5 the base is a template of a block of code, and 4 the abstract methods are the blanks to be 3 filled in. I personally use the template 2 method pattern to do my database resource 1 control in Java.

Score: 2

I have done much searching on this topic 39 myself (PHP Dependency Injection) and haven't 38 found much to my liking. A lot has been 37 written on the subject for other languages 36 (Google Guice - http://code.google.com/p/google-guice/ ; Java Spring), but I couldn't 35 find much available for PHP. Regardless 34 of the language, however, the challenges 33 are similar.

The three versions you list 32 in your question are the typical approach. Version 31 3 is the closest to the direction in which 30 I have seen the industry going. By shifting 29 the responsibility of creating your dependent 28 objects outside of your class, you are free 27 to manipulate them as you please in your 26 test code. However, the problem that I encountered 25 with that approach is that you end up with 24 long chains of dependent objects in your 23 constructor that can potentially not even 22 be used by the receiving object, but get 21 passed through to an secondary dependent 20 object. It gets messy and you lose knowledge 19 of what is coming from where.

The Dependency 18 Container example by @Arkh and @mmmshuddup 17 is a great start, but I nonetheless found 16 limitations with that approach as well. The 15 final solution upon which I arrived was 14 a custom built solution modeled somewhat 13 after the Cake Pattern popular in Scala. It 12 allows you to pass a single dependency into 11 each of your constructors AND it lets you 10 define the default construction of the dependent 9 objects per class. This frees you from long 8 dependency chains as well as losing control 7 of the default implementations of your dependencies.

I 6 called the system Diesel and I've been really 5 happy with it. I published the code on github 4 for anyone interested. You can get to it 3 from the blog I wrote on the subject, which 2 describes the basic usage as well as goes 1 into more detail on your question. http://developers.blog.box.com/2012/02/15/introducting-diesel-php-dependency-injection/

Score: 2

Dependency Injection is the idea of removing 16 the dependency between 2 components in order 15 to focus on why they are dependent.

Imagine 14 you have a component A that needs to use 13 the services of another component B.

If you 12 hardcode the existence of B inside A, then 11 you will be stuck when you will want A to 10 use the sames services, but implemented 9 by another component.

So usually, you define 8 a service interface that B and C will implement, and 7 you make sure that when you use A, you feed 6 it with objects compatible with the needed 5 interface.

In your case, you might consider 4 that your interface is a service on which 3 you can make a query.

Your first case is 2 the one that is the closer to the idea of 1 Dependency Injection.

More Related questions