I have a small framework and I coded it like this. I'm not sure if it is called dependency injection or not. I don't know if it is like a design pattern or not. I also don't know and wonder if passing $this as param is a bad practice.
Have a look at this; (Not a working example, just wrote those codes into browser for explanation.)
/* This is engine model */
require_once('Database.class.php');
require_once('Image.class.php');
require_once('Misc.class.php');
require_once('BBCode.class.php');
class FrameWork_Engine_Model
{
public $database, $config, $misc, $bbcode, $controller, $image;
function __construct($config)
{
$this->database = new Database($configParams);
$this->image = new Image($this);
$this->misc = new Misc($this);
$this->bbcode = new BBCode($this);
$this->controller = new Controller($this); //here I call Register controller depending on routing, in this case, register controller.
}
...
}
/* This is register controller */
class Register extends Base_Controller
{
/*I can access anything over Engine Model in my controllers */
$this->engine->database->query(); //I access database model
$this->engine->bbcode->tag('you'); //I access bbcode model
$this->engine->image->sanitizeUploadedFile(); //I access image model
//etc. I can access others models like this.
}
Basically, my controllers can access any models via engine model. I believe dependency injection is all about injecting dependencies into controllers? Like, my register controller needs a database model, routing model, and templating model to work. Here it has everything it depends on. Am I mistaken?
With those said, my questions are:
Is it a valid dependency injection example? If not, what it is? Does it have a name in design patterns?
If it is nothing related to dependency injection, what changes needs to be done to be DI?
Is passing $this parameter on newly created classes is a bad practise? If so, why?
Ps. I know asking 3 questions in a topic isn't something stackoverflow likes, but I don't want to copy paste entire text to ask them.
You are almost there.
Question 1
No, I don't see it as a valid dependency injection example. It resembles a bit a service locator (because you're injecting the entire container into your services and use it to "locate" dependent services).
Question 2
You're making a small confusion between dependency injection and a dependency injection container.
First of, dependency injection means pushing dependencies into an object at runtime instead of creating/pulling them.
To exemplify this:
//hardcoded dependecies
class BadService
{
public function __construct()
{
$this->dep1 = new ConcreteObject1();
$this->dep2 = new ConcreteObject2();
}
}
So in the example above, the BadService makes it imposible to wire other dependencies at runtime because they are already hard pulled into the constructor itself.
//service locator pattern
class AlmostGoodService
{
public function __construct(Container $container)
{
$this->dep1 = $container->getADep1();
$this->dep2 = $container->getADep2();
}
}
In the AlmostGoodService example, we've removed the hard dependencies from the previous example but we are still depending on a specific implementation of our container (meaning that our service is not reusable without providing the implementation for that container). This is the example that matches what you're doing.
//dependecy injection
class GoodService
{
public function __construct($dep1, OptionalInterface $dep2)
{
$this->dep1 = $dep1;
$this->dep2 = $dep2;
}
}
The GoodService service is not concerned with the creation of it's concrete dependencies and can easily be "wired" at runtime with any dependencies that implement the "protocol" of the $dep1 or the OptionalInterface for the $dep2 (therefore the name of Inversion of Control - the underlying concept behind Dependency Injection).
The component that does this wiring is called a dependency injection container.
Now, a dependency injection container, in it's simplest form, is nothing more than an object capable of wiring up your objects at runtime based on some form of configuration.
I said that you are almost there but there are some problems with your implementation:
the wiring should be lazy (you do not want to make all that work in your constructor, as your application would slow down considerably as it grows)
you should not pass the entire container ($this) as a dependency because then you fallback to a weaker inversion of control, namely a service locator. You should instead pass the concrete dependencies to your service constructors
Question 3
There are some cases when you'll find yourself wanting to pass the entire $container as a dependency to a service (namely controllers or lazy service factories), but generally it will be better to stay away from this practice as it will make your services more reusable and easier to test. When you're feeling that your service has too many dependencies, then that it's a good sign that you're service does too much and it's a good time to split it.
Prototype Container Implementation
So, based on my answers above, here is a revised (far from perfect) implementation:
/* This is the revised engine model */
class FrameWork_Engine_Model
{
function __construct($config)
{
$this->config = $cofig;
}
public function database()
{
require_once('Database.class.php');
return new Database($this->config['configParams']);
}
public function bbcode()
{
require_once('BBCode.class.php');
return new BBCode($this->database());
}
public function image()
{
require_once('Image.class.php');
$this->image = new Image($this->config['extensionName']);
}
....
public function register_controller($shared = true)
{
if ($shared && $this->register_controller) {
return $this->register_controller;
}
return $this->register_controller = new Register_Controller($this->database(), $thus->image(), $this->bbcode());
}
}
Now, to use your services:
$container = new FrameWork_Engine_Model();
$container->register_controller()->doSomeAction()
What could be improved? Your container should:
provide a way to share services - that is, to initialise them only once
be lockable - provide a way to lock it after configuration
be able to "merge" with other containers - that way your application will be really modular
allow optional dependencies
allow scopes
support tagging services
Ready to use DI Container Implementations
All of these are accompanied with clear documentation about Dependency Injection
Pimple - PHP 5.3 lightweight DI container
Symfony2 DI Container - PHP 5.3 feature full DI container
Juice DI - Small PHP 5.2 DI container
Your FrameWork_Engine_Model is a registry (Registry Pattern). Injecting the registry as dependency into all objects is kind of a misunderstood dependency injection. Technically it is DI, but you create a dependency from everything to everything and also take away the flexibility that DI should offer.
If your FrameWork_Engine_Model was meant to instantiate services and manage their dependencies, you could change it to an Inversion of Control Container (typical pattern related to DI)
No, not in general.
I won't argue your choice of class names and the responsibilities of your services and controllers, as I don't think it is within scope of this question. Just a remark: it looks like your controllers do too much. If you are interested in clean code, you might want to have a look at the Single Responsibility Principle and keep your controllers "thin", moving business logic and database queries to a service layer and output mechanisms like bbcode to views.
So, back to your example and how to change it to a sensible usage of Dependency Injection. A primitive IoC container could look like that:
public function createRegisterController()
{
$controller = new RegisterController();
$controller->setImage($this->getImageService());
// ...
return $controller;
}
public function getImageService()
{
if ($this->imageService === null) {
$this->imageService = new Image();
// inject dependencies of Image here
}
return $this->imageService;
}
The important point here is: Only inject the dependencies that are needed. And don't create a bunch of global variables disguised as DI.
Related
Doctrine examples usually make use of Doctrine's $entityManager. Hence, whenever I need to do anything in my app with Doctrine, I need to get the entity manager into my code. But how? .... I can inject it into my class, but still I need to create manager somewhere first. I can also make it use PHP's trait which I put into my class to make it Doctrine-enabled.
What I have done in my OOP code is something like this -- I defined a class DoctrineConnector in its own namespace of DoctrineConnector, and inside the class I have a static function getEntityManager. Inside, I read Doctrine configuration, paths, parameters, and create an $entityManager, and then I return it to the caller.
Whenever I need to read or persist something in my Doctrine-unaware code, I do this:
//Pricing.php
use DoctrineConnector\DoctrineConnector;
class Pricing
{
public function getPricing()
{
$entityManager = DoctrineConnector::getEntityManager();
//further Doctrine code to read DB
}
}
DoctrineConnector is now a dependency of Pricing. Obvious answer may be "inject $entityManager into Pricing". But Pricing is called from another class, and that other class is called from another class, etc so I will have to make essentially every class I call be aware of the ORM variable. I want to avoid that.
Is what I currently have just fine or is there a better way?
How ZF2 module system does it
Out of curiosity I looked into how ZF2 manages Doctrine module and from DoctrineORMModule, it uses ServiceLocator pattern to call the inside of controller. So one of the leading framework module systems is not that far off from my implementation.
Singleton Pattern
Adapted from http://www.phptherightway.com/pages/Design-Patterns.html
namespace ABC;
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;
class DoctrineConnector
{
private static $instance;
public static function getEntityManager()
{
if (null === static::$instance)
{
// Doctrine Config (from Docs)
include 'config/doctrine-config.php';
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
static::$instance = EntityManager::create($dbParams, $config);
}
return static::$instance;
}
protected function __construct()
{}
private function __clone()
{}
private function __wakeup()
{}
}
//to call
$em = DoctrineConnector::getEntityManager();
//if used later in the code - calls same instance
$em = DoctrineConnector::getEntityManager();
There are a couple of popular ways to get a dependency inside the class.
make the class aware of project environment and let the class locate the dependency (what you did with DoctrineConnector)
use dependency injection (what you are trying to achieve)
In your case, your class now depends on DoctrineConnector and is going to work as long as it can find DoctrineConnector. If you port your class to another project where DoctrineConnector isn't defined, your code isn't going to work.
Normally dependency injection is a decision you make when you start your new project. If you already have a large hierarchy of classes, the injection code will bubble up your hierarchy and there is going to be a lot of work refactoring your code. You might want to think wether you really need that and wether it's going to be worth your time.
If you are writing code for one particular app and have no plans to migrate it to other projects, then you probably don't care about dependency injection. Actually, without injection your code is going to be shorter and easier (faster) to write and understand. On the other hand if you have pieces of code that you want to be independent of the app, you might use dependency injection only for those code segments.
If you haven't injected ORM yet, chances are that the rest of the code is tightly coupled with your app as well, and injecting entityManager isn't going to make your code much more portable.
I'm making my own primitive MVC framework with PHP, and I'm wondering where I should load/instantiate corresponding controller dependencies?
In the constructor of each controller (tightly coupled) or inject them (loosely coupled)?
The only part of the latter that I'm not too sure of is for the dependencies to be instantiated on bootstrap level, outside of the MVC paradigm, before being injected. Not every controller uses the exact same dependencies besides the default parent ones. I would have to instantiate them all, which would also create a lot of overhead.
I've seen some existing frameworks do it like $this->load->model('model'); // CodeIgniter in the constructor, but I have no clue on why they're doing it like that.
I would suggest you inject the dependencies, so your controllers are less coupled to your framework. This will make a switch to another framework easier.
About instantiating dependencies: I suggest you use (or implement) a dependency injection container. This container should contain factories that can instantiate services.
In an ideal situation your controllers are services too (meaning they too have factories in the dependency injection container).
This way only the controller you need for a particular request will be instantiated, and therefor only its dependencies are instantiated.
When building you own framework, this means that after the routing phase (when the correct controller is known), the framework should grab that controller from the container. The container itself will make sure all dependencies that are needed will be provided.
Have a look at Pimple for an example of a simple dependency injection container.
PS: That line from CodeIgniter looks a lot like the service locator pattern. This pattern is similar to dependency injection, but does not provide full inversion of control.
Q: Where should i load/instantiate corresponding controller dependencies?
There are multiple ways.
The load and instantiation concepts are basically "before/outside" and "after/inside".
Before and outside means, that you load the file containing a class (which you want to instantiate and pass to the controller), before you load the controller.
But how do you know, what the controller needs, before loading the controller? Uh..
Dependency Description Files
A description file comes into play, describing the wiring between your controller and it's dependencies. In other words, you can see the dependencies of your controller by looking at it's dependency description file. This concept is often used by Dependency Injection tools, which analyze the object and pull the dependencies names out automatically. It's also possible to maintain such a wiring configuration file manually. But it's tedious.
Service Locator
A Service Locator is a instantiation helper for dependencies.
Basically, it contains the same information like a dependency description file, but this time in form of a registry. The link between parts of your application becomes this registry.
Both strategies introduce overhead. It's a trade-off. When you change the perspective and look at things from an application with maybe 500+ classes, then you realize that a dependency injection tool is sometimes worth it.
Manual Injection
via Constructor Injection.
After and inside means, that you load the file containing your controller and then start to care about the dependencies.
At this point the class is not instantiated, yet, but the autoloader might do it's dirty deeds behind the scene. He evaluates the use statements at the top of your controller file. The use statements declare namespaced classes, which the autoloader resolves to actuall files and loads them. You might then start to use these classes as dependencies in your controller. This is probably the easiest way to solve your problem and i strongly suggest looking into the topics autoloading with namespaces and use-statements.
When the class is instantiated, you have the following possiblities:
use might use Setter Injection or Reference Injection to set the dependencies to the object. This requires that your Constructor Dependencies are already solved or your constructor is empty.
It's possible to combine these strategies.
Q: What does this do $this->load->model('model'); // CodeIgniter?
CodeIgniter is a legacy application framework. It was created in times, when namespaced autoloading wasn't available. $this->load is a basic class loading helper. This is the opposite of an "auto"loader, (which surprise, surprise) loads things automatically.
CodeIgniters loader class is used to load various other classes, like libraries or files from the view, helpers, models or user defined stuff. This is again the concept of a registry. Here the registry just knowns where things are in your application layout and resolves them. So $this->load->model('model'); means that the modelfunction must have some piecies of information, about the position of model files in your application.
You provide a model name and the path for the file is constructed by model.
And this is exaclty what it does (except a bit of overhead): https://github.com/EllisLab/CodeIgniter/blob/develop/system/core/Loader.php#L223.
Since I'm a Symfony developer, I can only give you a reference to Symfony.
I think you should do like they are doing in Symfony by thinking about what you need in each
Controller object.
At least, you need :
a Request object
and a Model loader object that gives you every Model you need.
Create a BaseController that implements these few functions and then extend it with custom Controllers.
You can also take a look on Silex : http://silex.sensiolabs.org/ a Micro Framework
Hope it helps.
When do you say "In the constructor" you mean to pass in the conatiner and pull the dependencies from them (in the constructor)?
<?php
class SomeController
{
public function __construct($container)
{
$this->service1 = $contanier->get('service1);
}
//...
}
I advice against that, though simpler and easier you will be coupling your controllers to the container thus using a ServiceLocator instead of truly inversion of control.
If you want your controllers to be easy unit-testable you should use inversion of control:
class SomeController
{
public function __construct($service1)
{
$this->service1 = $service1;
}
//...
}
And you can even create your controller as a service inside the container:
// this uses Pimple notation, I hope you get the point
$container['controller'] = function($c) {
return SomeController($c['service1']);
}
Use proxy services to lazy load them
Also if your controllers needs more than some services and you won't be using all of them you can:
1) Use proxy services in order to lazy load the service only when they are really needed
<?php
class ProxyService
{
/**
* #var Service1Type
*/
private $actualService;
public function __construct()
{
$this->actualService = null;
}
private function initialize()
{
$this->actualService = new Service1(); // This operation may take some time thus we deferred as long as possible
}
private function isInitialized()
{
return $this->actualService === null;
}
public function someActionOnThisService()
{
if (!$this->isInitalized()) {
$this->initalize();
}
$this->actualService->someActionOnThisService();
}
There you have a simple proxy object with lazy loading. You may want to check the fantastic Proxy Manager Library if you want to go that route
2) Split your controller
If your contoller has too many dependencies, you may want to split it.
In fact you may want to read the proposal by Paul M. Jones (lead developer of Aura Framework) about MVC-Refinement, IMHO is a good read even though you may not fully agree with it.
Even if you split your controller in order to reduce the dependencies, lazy loading your dependencies is a good idea (obviously you'll have to check weather if its doable in your context: more work in order to gain more speed).
Maybe you need to define __autoload() function before you try to load the Classes which is not loaded yet. Like:
function __autoload($className) {
require "/path/to/the/class/file/$className.php";
}
My example is very very simple to auto require the file which the class definition is in.
You can also use if-else statement or switch statement in that function to fit your own situations smartly.
The __autoload() function is called when PHP doesn't find the class definition, works for new, class_exists(), call_user_method(), etc, and absolutely for your dependences/parents classes. If there is still no class definition after __autoload() is called, PHP will generate an error.
Or you can use spl_autoload_register() function instead of __autoload() more gracefully.
For more information, you might want to see:
http://php.net/manual/en/function.autoload.php
http://php.net/manual/en/function.spl-autoload-register.php
I want to know how to implement a dependency injection container using php(for study). I get the concept of dependency injection and i can implement it but I can only factor out until controllers of php frameworks.
Meaning the whole instantiation, injections, and etc happen in the controller. Like
class SampleController{
public function action1(){
$sample_object = new ObjectToInject();
$dependent_object = new DependentObject($sample_object);
$dependent_object->doSomething();
...
etc
}
}
Now what I'm saying is the controller gets bloated if the logic gets more complicated. I know that my controller gets bloated, doesn't that mean that it is still not so maintainable?
Questions:
Is my assumption correct that the controller now have all the logic?
Then what is the use of a Dependency Injection Container? and is this the same as what he said as bootstrapper in this article?
Kindly explain what Symfony2 Dependency Injection Containers do.
Please give me a concrete example of Dependency Injection Container using php.
Am I correct that in unit testing, only dependent classes are to be tested and independent classes does not need to be tested.
Kindly correct me if me questions are vague.
Thanks
This is a really loaded question. To quickly answer your points:
(1) No. That is not correct. While you have to do your wiring somewhere, it should not be in your controllers. Your controllers should receive only the fully built objects they need to do their jobs. Don't give them more than they need.
Example:
example
class UserController
{
public function __construct(UserRepository $UserRepository)
{
$this->UserRepository = $UserRepository;
}
public function showUser($id)
{
$User = $this->UserRepository->find($id);
}
}
Note that UserController only has UserRepository as a dependency? UserRepository meanwhile might look like this:
class UserRepository
{
protected $registry = array();
public function __construct(UserFactory $UserFactory, UserMapper $UserMapper)
{
$this->UserFactory = $UserFactory;
$this->UserMapper = $UserMapper;
}
public function find($id)
{
if (isset($this->registry[$id]) {
return $this->registery[$id];
}
$User = $this->UserMapper>find($id);
$this->registry[$User->id] = $User;
return $User;
}
public function findOrNew($id)
{
if (!$User = $this->UserMapper->find($id)) {
$User = $this->UserFactory->make(array('id' => $id));
}
return $User;
}
}
Your UserController should have no knowledge of the UserFactory or the UserMapper objects if it does not need them directly. Further, your UserRepository should not know about the DataAccessLayer that gets injected into UserMapper. UserMapper also doesn't need to know that DataAccessLayer is relying on a PDOConnection object instead of something else.
(2) The use of a container is to do what you SHOULDN'T be doing in your controllers: wiring up all of your dependencies. The simplest, easiest way to understand what a DI Container is and how it works is to download and use Pimple. It's a really simple, straight-forward DI container and it's well documented: https://github.com/fabpot/Pimple
(3) That's a big topic. Symfony's is a more advanced version of Pimple. I suggest learning Pimple and then reading through the documentation for Symfony and seeing the examples they use. Also check out Laravel's, or even PHP-DI https://github.com/mnapoli/PHP-DI
(4) As before see Pimple: https://github.com/fabpot/Pimple
(5) You should strive to test all of your code logic as long as there is something to test. Presumably, each method/function/class in your application does something, so you should test that it's doing what it should do. What you don't have to do, is test that any of its dependencies are doing what they should do, because you are presumably testing those. You trust that the data being passed into one class or method has been tested, and then you test only what the new class/method is meant to be doing.
But again, I highly recommend learning on Pimple, and then trying out something like PHP-DI to see how auto-reflection and auto-resolving dependencies works. The best way to do it is just immerse yourself in a variety of containers and play around with them.
Instantiating dependencies is not "logic", it's just configuration.
AmgLauncher wrote a great answer, I want to provide a simpler one: controllers are no different than services. You should use dependency injection on controllers, just like for services.
Here is the problem: Symfony doesn't encourage that (through their documentation at least). Don't blindly follow Symfony's DIC documentation.
So in the end, the question is: but what/who will construct my controller if it has dependencies?
That's the job of the container. The container will build your controller and all your services. The catch is that some frameworks don't work that way. In Symfony 2, there's an option for that: Controllers as services.
If you were to use Pimple, you would have to write all the code that creates all your controllers. That's useless/boring code. Pimple is not really suited for that.
As AgmLauncher suggested, have also a look at PHP-DI, and for example this guide about how to write controllers. I recommend also you to read this simple introduction to What is a DI container and how it works. (disclaimer: I'm the maintainer of PHP-DI)
I know some OOP and have read this and that, but am not a hardcore OOP guy and have no formal training and can't rattle off why something should use dependency injection or not, and may not be able to identify all dependencies in a design, hence my question.
Answering a question here on SO (Using a object in methods of other objects) I started to doubt myself. As far as dependencies, is one of these better or worse or both acceptable? Any design limitations?
I have read and understand both but haven't ever come across a comparison. Why would one be better used in a design, etc.
Dependency Injection:
class myClass {
private $db;
public function __construct($db) {
$this->db = $db;
}
}
Registry (maybe also something else):
class myClass {
private $db;
public function __construct() {
$this->db = Registry::get('db');
}
}
It has a lot to do with testability.
In your example, the first (Dependency Injection) is better. The reason it's better is because it accepts db as an argument, which means this is testable, you can use a mock db for testing and test myClass does the right thing with it.
The second example (Registry) is not recommended as not only myClass depends on db, it now also depends on Registry, and the worst part it's that it knows how to get a db. It's too smart, it should be dumb like the first one, dumb things are more testable, smart things are not.
Both methods are possible implementations of dependency injection. Basically dependency injection means to define a way to configure (inject) the classes to be used at runtime in order to make to code more flexible compared to using using hard coded class names and constructors in the code. Dependency injection follows a principle called inversion of control.
This is especially interesting for testing code but can be used in a variety of other scenarios where you want to make an application flexible and maintainable.
While dependency injection mostly is referred to as DI container, it can generally be done using a couple of different methods - which may also coexist. Here comes an (incomplete) list:
using a dependency injection container
pass class dependency as constructor or method args
using a central registry (as long as it is configurable)
using setter methods to set dependencies
using configuration files
user input
...
A dependency injection is required because the object needs certain data to perform its functions correctly.
Dependency Injection can be performed in three different ways:
If Object A depends on object B, then you can create object A while creating object B
You can use some external class ( like Registry, configuration files etc ) to load the dependency objects, This will decouple the creation of your object from the dependency creation. This is called locator pattern where your object creation is dependent upon the locator to load the objects.
You can create the dependency elsewhere and provide it directly to the dependent object. This is called 'manual injection'
Whenever you do any of these, you are already doing dependency injection:
Constructor injection
public class ClassA
{
// declares the dependency in the constructor
public function ClassA( dependency1:String )
{}
}
// and the dependency is created while instantiating the object
var objA:ClassA = new ClassA("Hello World");
Public property injection
public class ClassA
{
// declares the dependency as a public property
public var helloStr:String;
}
var obj1:ClassA = new ClassA();
// dependency is fulfilled by setting a public property after instantiation:
obj1.helloStr = "The Zen Master";
I have a class which depends on 3 classes, all 3 of which have other classes they rely on. Currently, I'm using a container class to build up all the required classes, inject them into one another and return the application.
The simplified version of the container looks something like this:
class Builder
{
private $_options;
public function __construct($options)
{
$this->_options = $options;
}
public function build()
{
$cache = $this->getCache();
$response = $this->getResponse();
$engine = $this->getEngine();
return new Application($cache,$response,$engine);
}
public function getResponse()
{
$encoder = $this->getResponseEncoder();
$cache = $this->getResponseCache();
return new Response($encoder,$cache);
}
// Methods for building each object
}
I'm not sure if this would be classified as FactoryMethod or a DI Container. They both seem to solve the same problem in the same way - They build objects and inject dependencies. This container has some more complicated building methods, like loading observers and attaching them to observable objects.
Should factories be doing all the building (loading extensions etc) and the DI container should use these factories to inject dependencies? That way the sub-packages, like Cache, Response etc, can each have their own specialised factories.
A DI Container is definitely a Factory, but it's a general-purpose factory.
However, if you use it in a pull-based way by asking it to create dependencies for you every time you need them, you would be employing the Service Locator anti-pattern. That's just a general-purpose factory and actually has little to do with DI.
True Dependency Injection is, as the name implies, push based. You write all your code using simple patterns like Constructor Injection, and use the DI Container to resolve your entire dependency graph in one go in the application's Composition Root, injecting all dependencies into their respective consumers.