Dependency injection/dependency injection containers in MVC web app I just learned about dependency injection/dependency injection containers, and I realize that the controller in my MVC web application is hard to test.

My original controller class: 

class Controller
{
    protected $db;
    private $article;
    private $nav;

    public function __construct($db) 
    {
        $this-&gt;db = $db;
        $this-&gt;article = new Article($this-&gt;db);
        $this-&gt;nav = new Nav($this-&gt;db);
    }

    public function render($template) 
    {
        var_dump($this-&gt;article-&gt;getRow());
        var_dump($this-&gt;nav-&gt;getRows());
    }

}


This is my test using DI/DIC in my MVC app:

Controller

class Controller
{
    private $container;

    public function __construct() 
    {
    }

    public function render($container,$template) 
    {
        $this-&gt;container = $container;
        var_dump($this-&gt;container-&gt;getArticle($url = 'home'));
        var_dump($this-&gt;container-&gt;getNav());
    }

}


Container: holds all objects which generate data from the database

class Container
{
    protected $db;
    private $article;
    private $nav;

    public function __construct($db) 
    {
       $this-&gt;db = $db;
    }

    public function setArticle() 
    {
        if (is_null($this-&gt;article)) 
        {
            $this-&gt;article = new Article($this-&gt;db);
        }
        return $this-&gt;article;
    }

    public function setNav() 
    {
        if (is_null($this-&gt;nav)) 
        {
            $this-&gt;nav = new Nav($this-&gt;db);
        }
        return $this-&gt;nav;
    }

    public function getArticle($url) 
    {
        return $this-&gt;setArticle()-&gt;getRow($url);
    }

    public function getNav() 
    {
        return $this-&gt;setNav()-&gt;getRows();
    }
}


Models

class Article
{
    public function __construct($db) 
    {

    }

    public function getRow($url) 
    {
        return "row 1";
    }
}

class nav
{
    public function __construct($db) 
    {

    }

    public function getRows() 
    {
        return "rows nav";
    }
}


Usage

$db = 'pdo connection';
$template = 'template.phtml';
$container = new Container($db);
$controller = new Controller();
$controller-&gt;render($container,$template);


Questions:


Am I doing it correctly or not?
Do the improved Controller and Container above make sense to you if you were a developer going to pick up  this application's development?
Do I need any interfaces or traits as part of the app? If so, why?
You are not even doing Dependency Injection here. In your controller constructor for example

public function __construct($db) 
{
    $this-&gt;db = $db;
    $this-&gt;article = new Article($this-&gt;db);
    $this-&gt;nav = new Nav($this-&gt;db);
}


sure you are injecting the $db but that is not a dependency for as long as it does not enforce the type of object required. In this case I can inject anything, say, a string, a number, an object of some other class, array or pretty much everything else. How is constructor going to control the behaviour of this object ?

Furthermore, you are 'newing' up the objects in constructor. Don't you think the objects you are initialising inside the constructor should instead be injected into it ? That is what IoC does.

The solution to first problem is Type Hinting. What you do here is you define the type of argument and only defined type can be passed to the constructor as argument. For more flexibility (which you'd more likely want in case of database connection) you can define an interface and inject an implementation of it into the constructor. So for example you define an interface DatabaseConnection like this:

interface DatabaseConnection {
    public function prepareQuery($queryString);
    public function addQueryBindings(array $queryBindings);
    public function run();
}


Now you can create multiple implementations of this interface and have IoC inject them into constructor. So now you can have MySQLDatabaseConnection, PostgreDatabaseConnection, MSSQLDatabaseConnection, SQLiteDatabaseConnection each one implementing DatabaseConnection and then you type hint the constructor of controller to accept DatabaseConnection

public function __construct(DatabaseConnection $db) 
{
    $this-&gt;db = $db;
    $this-&gt;article = new Article($this-&gt;db);
    $this-&gt;nav = new Nav($this-&gt;db);
}


This constructor will allow any object which implements the DatabaseConnection interface and throw error if you try to inject anything else that is not a descendent of this interface.

Now that type hinting and interface is out of the way, I hope you can already see this but let me point it out.
The objects you are initialising inside controller constructor can be injected by IoC, this will also eliminate the need to have DatabaseConnection injected into a controller (which looks a terrible idea to me). So here is the controller constructor freshen up

public function __construct(Article $article, Nav $nav) 
{
    $this-&gt;article = $article;
    $this-&gt;nav = $nav;
}


and you'll also need to change the constructor of both Article and Nav class to type hint the DatabaseConnection so that IoC can do its things

class Article
{
    public function __construct(DatabaseConnection $db) 
    {
        //...
    }
}


and 

class Nav
{
    public function __construct(DatabaseConnection $db) 
    {
        //...
    }
}




The container, as you call it, is also not an IoC container (Inversion Of Control), It is not doing dependency injection just holding pre-initialised objects into itself. If you want Dependency Injection you need an IoC Container for that.
I dont think I can explain the architecture of an IoC container in a post here but with IoC in place you'll be able to initialise objects auto-magically with proper dependency already injected into it. So for example when you initialise our new controller from IoC container you will have an object of Controller with Article and Nav injected into it and both of them will have DatabaseConnection injected into them.

There are many IoC containers available on Github, some standalone and some as a part of a framework.