Reputation: 958
I'm trying to implement a simple DI in a pure OOP application. I wanted to use Dependency injection to manage many services ( Database, RequestValidator, Cache etc. ). I have read many blogs and liked this one from tech-tajawal but I could not really understand where should I include the container that tech-tajawal wrote. Can someone please show me how to do it?
I want it clean and thus want to use constructor based injection. So If I have a class, let's say AbstractBaseController
which will inject a dependency called Request
, so I will write:
php:
<?php
namespace src\controllers;
use system\middlewares\Request as Request;
abstract class AbstractBaseController {
private $request;
public function __construct(Request $request) {
$this->request = $request;
return $this;
}
}
But this simply throws
Fatal error: Uncaught TypeError: Argument 1 passed to src\controllers\AbstractBaseController::__construct() must be an instance of system\middlewares\Request, none given`
I think the container from tech-tajawal has to be included in my project root someway but I don't know how.
Please excuse my naivety here as I always was framework dependent.
Upvotes: 0
Views: 350
Reputation: 1224
You should instantiate your container at the very beggining of your application (think of a bootstrap class, or even at the top of index.php itself, considering a very simplistic application), because you will need the container to be ready before all the subsequent instantiations of services.
The only other thing that could probably be executed before the container instantiation are those related to configuration, because those are usually needed for the container to work properly (configuration parameters, PSR-4 autoloading configuration, etc).
For example, suppose that you have a class called MyController
that extends the abstract class AbstractBaseController
.
Then, on index.php, for example, you could instantiate your container and your controller:
//index.php
$container = new Container();
$controller = $container->get('namespace\of\MyController');
$controller->render();
When you do that, all the dependencies from the constructor would be handled by the autowiring module of your container library.
In a real life application, the instantiation of a controller would be usually handled inside a router, which maps URL addresses, methods and parameters to different classes to be loaded by the container.
One rule of thumb with autowiring, is that you can never call new namespace\of\MyController()
directly anymore, because instantiating it manually would require you to pass each of the constructor dependencies (so you are not really using the autowiring feature). The right way to instantiate it is always by using $container->get('namespace\of\MyController')
.
Upvotes: 1