3

Please forgive the possible naivety of this question, however I am getting myself really confused. It appears that it is good practice to use dependancy injection to decouple your code so that your classes are loaded with their dependancies. PLease imagine the following where Class Foo has a dependancy of class Bar

namespace Classes;

class Foo{

    protected barInstance;

    public function __construct(Bar $barInstance){
        $this->barInstance=$barInstance;
    }

}

However if you are autoloading your classes then surely the following does the exact same thing without the need of DI?

namespace Classes;
use Classes/Bar;

class Foo{

    protected barInstance;

    public function __construct(){
        $this->barInstance=new Bar;
    }

}

Thanks to any responders.

2
  • 6
    Because sometimes you don't want a new Bar, but a specific existing Bar. Commented Apr 26, 2016 at 19:26
  • 2
    And because separating concerns (class A not knowing how to create an instance of B) often makes it easier to unit test your code (you can just pass in a mock object, etc). Commented Apr 26, 2016 at 19:30

4 Answers 4

3

Autoloading ensures your class is defined when you reference it. Dependency injection gives you flexibility over what instance of an object you use.

In your example, lets say your Bar class manages a database connection. And lets say you sometimes want to connect to a different database.

public function __construct(){
    $this->barInstance = new Bar();
}

Now you must refactor your Foo class to handle the change because you've tightly coupled it with an instance of Bar.

public function __construct(Bar $barInstance){
    $this->barInstance = $barInstance;
}

Now, without changing Foo, I can instantiate a different instance of Bar for different situations. A commonly useful example of this is in unit tests.

In both cases autoloading made sure that Bar and all of its own dependencies are are defined outside of Foo.

Sign up to request clarification or add additional context in comments.

Comments

2

Take the example with a database connection.

you have

public class foo {
    public function __construct(DbConnectionInterface $db) { ... }
}

public class foo2 { 
    public function __construct(DbConnectionInterface $db) { ... }
}

...

and so on

In your "service container" you have something like that

$db = new PdoDbConnection(); // which implements DbConnectionInterface

$service['foo'] = new foo($db);
$service['foo2'] = new foo2($db);

If tomorrow you want to use something else than pdo, then you just have to make a new connection implementing the interface and then you can change your db connection in one place

$db = new NotPdoDbConnection(); // which implements DbConnectionInterface

$service['foo'] = new foo($db);
$service['foo2'] = new foo2($db);

If you didn't use the DI, then you should have changed your new PdoConnection() to new NotPdoConnection() in all the classes using this class. But the autoload cannot help you some much in this case. As said by lsklyut his answer its two different concepts.

its a "dummy" case but you can read some interesting articles about DI

http://fabien.potencier.org/what-is-dependency-injection.html http://www.martinfowler.com/articles/injection.html

Comments

0

These are two separate concepts. Autoloading will allow you to not have to include files in your scripts and allow you to separate your classes by concept. As far as dependency injection, if Bar had additional dependencies and could not simply be instantiated by using new Bar(), but rather new Bar($dep1, $dep2), then your logic to create Bar would be buried inside Foo's constructor, as well as the constructor of any other class which requires Bar. By inverting the dependency creating Bar somewhere else before injecting it, you're relieving Foo of that additional responsibility.

Comments

0

Autoloading and dependency injection are unrelated concepts.

The autoloader knows how to load the classes. When a simple statement like new Foo() runs, the interpreter needs to know the definition of the Foo class. If it doesn't already know it then it invokes the autoloader(s) until the class becomes available. The autoloaders know where each class is defined and include the correct file.

The dependency injection container knows how to build objects of various types. It doesn't know (and doesn't care) about class loading. It assumes that when it runs new Bar() the class Bar is already defined (or it can be autoloaded).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.