I have build a in-house MVC PHP framework and now I am struggling on implementing DI Container. I've adopted the Pimple as a DiC, I have read the book by Chris Hartjes "The Grumpy Programmer's Guide To Building Testable PHP Applications" (which I find a very good and inspiring read, will recommend it highly!), which talks eased me to understand more about TDD. Anyway, If I get a DI in the core of the framework, how should I populate the definitions and ho should I pass it along.
Injecting the container(Injecting in the application object all the way to the user created controller). - WRONG
Forcing the dev-user to 'populate' it in the Bootstrap - WRONG
Singleton - VERY WRONG
Observer Pattern (DiC attached to the observer. Observer as a front end to DiC) - ?(Probably the worst idea :D )
Then how to make the core DiC available in the whole framework (for, lets say, injecting the Configuration Object), without creating any dependencies, unnecessary forcing the user to code it or adding the overhead of creating XML/JSON or any other.
PS:
** I do believe that I will see a lot of answers about the Inversion-of-Control (IoC) and Service Locator. Which I cant seem to get exactly how to implement them.. Reference me to a simple/basic guide.
(disclaimer, I'm the developer of PHP-DI)
I don't really understand your question, it seems to me that if you have full control over the MVC framework, then using DI and a DIC should be pretty easy. Here is a copy of the introduction to DI on PHP-DI homepage:
Application needs FooController so:
Application gets FooController from the Container, so:
Container creates SomeRepository
Container creates BarService and gives it SomeRepository
Container creates FooController and gives it BarService
Application calls FooController
FooController calls BarService
BarService calls SomeDependency
SomeRepository does something
The Container is in charge of creating all the objects (the object graph), and then the non-framework code (controllers, services, …) works without EVER calling the Container.
Then how to make the core DiC available in the whole framework?
Do not make it available in the whole framework.
Each component (object) should have its dependencies injected (for example in the constructor). The container will inject them (because the container creates all the objects), and the container should be called at the root of your application (the front controller).
Example: you want to inject the Configuration object in a controller:
class MyController {
private $configuration;
public function __construct(Configuration $configuration) {
$this->configuration = $configuration;
}
}
Since that the role of the DIC to create that controller, it will inject the configuration object.
Also, I don't think you should inject the whole configuration object, but just the values you are interested in (but that's another debate).
And also, if you have questions about how to write your controllers, maybe you should read this: Controllers as services?.
Related
I am looking for a php implementation or a design pattern something like this (just a very basic skeleton example):
namespace Contract {
interface Application {...}
interface EntryPoint {...}
}
namespace RestApi {
class Module {
/** #return Contract\EntryPoint */
public function getEntryPoint(Contract\Application $application){...}
}
class EntryPoint implements Contract\EntryPoint {...}
}
namespace BusinessLogic {
class Module {
/** #return Contract\Application */
public function getApplication(){...}
}
class Application implements Contract\Application {...}
}
$dependencyResolver = new DependencyResolver();
$dependencyResolver->parse(new RestApi\Module());
$dependencyResolver->parse(new BusinessLogic\Module());
$dependencyResolver->invoke(function (Contract\EntryPoint $entryPoint){
$entrypoint->handleRequest();
});
I want to loose couple every modules I am using in my application, so I intend to design interfaces, maybe abstract classes with validation to make a well defined interface for every module type. I haven't found a solution for this problem, ppl usually inject things with IoC container, which does not tell anything about the common interface between two modules...
Do you know a design pattern which solves this problem, or a de factor standard php implementation/framework for this?
note: IoC container is not a solution, I want to inject the dependencies with well defined interfaces, not to pull them from a DI container or service locator... I don't want my modules to know anything about how they get their dependencies...
edit:
I updated my question because I don't think my code was obvious for everyone. A created a class diagram to ease the understanding of it:
Okay, so this diagram contains a description of a single environment. We usually use different environments for example: test, development, production, etc... Each of these environment contains different modules, for example by testing and developing we usually turn off email sending, so one of the modules contains a mock php mailer in those environments... As you see by cross-module dependency the classes depend on contracts, not directly on each other. This way the code of the modules is loose coupled...
I intend to describe this dependencies (for example with annotations) and inject them on an automated way somehow. This is a difficult task, because by PHP I have to load only the classes which are necessary to handle the request. For example:
So I have to use lazy load somehow, for example I could inject factories, but I don't like that idea, I want to inject the dependency itself, not a factory...
Be aware that the contract interface does not know anything about its implementations, so I have to publish somehow those implementations by every module and find them from the other modules... Most of the DI container implementations solve that problem, but I don't want to inject factories or DI containers into my modules. I want them to depend on the contracts only and nothing else...
Matthieu Napoli recommended to use just a single IoC container with different config by each of the environments, but I don't see how this would solve my problem. That DI container would instantiate every class with cross-module dependency, so I would move the whole config of every modules into a huge main config file. Even by a simple project I'd have about 20 classes (languages, users, identification-factors, user-identification-factors, contacts, user-contacts, roles, user-roles, permissions, role-permissions, articles, comments, etc...) and at least 3 modules (presentation layer, business logic layer, data access layer). So that main config would contain the instantiation of at least 60 classes from different modules... That would be pretty hard to maintain and I am almost certain that it would result a lot of code repetition by configs of different environments... Yes maybe splitting the config files can reduce the pain, but I guess I wont know the advantages and drawbacks of this solution until I start to use it on a complicated project. Another problem with this approach that how should I implement the lazy load without injecting the IoC container itself into every class with cross-module dependency? I think I need proof or example code, that this approach really works well by this problem domain...
Currently I am thinking on something similar than require.js does with AMD javascript modules, but that injects the IoC container as well by lazy load. You have to use the require("moduleName") from inside the modules if you want to load a dependency which you don't want to use in your code, just in case when it's really necessary. Ofc that require is just a sugar syntax of container.get("moduleName")... Currently I don't see how to solve that problem. I think every of my modules should have one or more DI containers, call them module containers. Those module containers can handle the cross-module dependencies. By lazy load the module containers would pull down the cross-module dependencies of each class from a main container, which would automatically register every module container and every class instantiated by them. In this scenario only the module containers would know about the main container if I cannot solve lazy load without injecting a factory or a DI container or a service locator... Ofc this is the last resort, I think I can do the lazy load somehow without injecting the main container into the module containers. Or at least I can do it somehow with a sugar syntax, for example:
class ModuleContainer {
public function setCrossDomainDependency(Contract\Dep $crossDomainDependency){
//...
}
/** #return Contract\Dep */
public function getCrossDomainDependency(){
//...
}
}
My purpose to use the same ModuleContainer instance regardless of having a MainContainer. I'll check the reflection api, maybe I am able to override the getCrossDomainDependency somehow at runtime. If not then I think the only solution to inject factories or the main container... Nah but this is my solution...
How would you solve this problem?
A IoC container is exactly the solution.
I want to inject the dependencies with well defined interfaces, not to pull them from a DI container or service locator
Then don't use the container as a service locator. That's exactly what a DI container is meant for.
Here is your example using PHP-DI:
$containerBuilder = new ContainerBuilder();
$container = containerBuilder->build();
// Configure RestApi\EntryPoint to use for Contract\EntryPoint
$container->set(Contract\EntryPoint::class, \DI\link(RestApi\EntryPoint::class));
// Configure BusinessLogic\Application to use for Contract\Application
$container->set(Contract\Application::class, \DI\link(BusinessLogic\Application::class));
// Run
$entryPoint = $container->get(Contract\EntryPoint::class);
$entryPoint->handleRequest();
Of course my example here is not perfect. I would suggest to separate the configuration part from the execution part. I would put the configuration in a configuration file (look here for how).
Important: Yes, in that example I fetch something from the container. That is exceptional. That should happen only once or twice in your application.
You have to use the container at some point, at the root of your application (i.e. the entry point of the app), to construct the object graph (or dependency graph).
I am not suggesting that you call get() on the container everytime you need a dependency. I am suggesting that you use dependency injection instead, and that you call get() only at the entry point of the application.
Example of defining with a factory:
$container->set(Contract\EntryPoint::class, \DI\factory(function (Container $c) {
return new RestApi\EntryPoint($c->get('some.parameter'));
}));
My understanding:
A dependency is when an instance of ClassA requires an instance of ClassB to instantiate a new instance of ClassA.
A dependency injection is when ClassA is passed an instance of ClassB, either through a parameter in ClassA's constructor or through a set~DependencyNameHere~(~DependencyNameHere~ $param) function. (This is one of the areas I'm not completely certain on).
An IoC container is a singleton Class(can only have 1 instance instantiated at any given time) where the specific way of instantiating objects of those class for this project can be registered. Here's a link to an example of what I'm trying to describe along with the class definition for the IoC container I've been using
So at this point is where I start trying use the IoC container for more complicated scenarios. As of now it seems in order to use the IoC container, I am limited to a has-a relationship for pretty much any class I want to create that has dependencies it wants to define in the IoC container. What if I want to create a class that inherits a class, but only if the parent class has been created in a specific way it was registered in the IoC container.
So for example: I want to create a child class of mysqli, but I want to register this class in the IoC container to only instantiate with the parent class constructed in a way I've previously registered in the IoC container. I cannot think of a way to do this without duplicating code (and since this is a learning project I'm trying to keep it as 'pure' as possible). Here are some more examples of what I am trying to describe.
So here are some of my questions:
Is what I'm trying to do above possible without breaking some principle of OOP? I know in c++ I could use dynamic memory and a copy constructor to accomplish it, but I haven't been able to find that sort of functionality in php. (I will admit that I have very little experience using any of the other magic methods besides __construct, but from reading and __clone if I understood correctly, I couldn't use in the constructor it to make the child class being instantiated a clone of an instance of the parent class).
Where should all my dependency class definitions go in relation to the IoC? (Should my IoC.php just have a bunch of require_once('dependencyClassDefinition.php') at the top? My gut reaction is that there is a better way, but I haven't come up with one yet)
What file should I be registering my objects in? Currently doing all the calls to IoC::register() in the IoC.php file after the class definition.
Do I need to register a dependency in the IoC before I register a class that needs that dependency? Since I'm not invoking the anonymous function until I actually instantiate an object registered in the IoC, I'm guessing not, but its still a concern.
Is there anything else I'm overlooking that I should be doing or using? I'm trying to take it one step at a time, but I also don't want to know that my code will be reusable and, most importantly, that somebody who knows nothing about my project can read it and understand it.
Put simply (because it's not a problem limited to OOP world only), a dependency is a situation where component A needs (depends on) component B to do the stuff it's supposed to do. The word is also used to describe the depended-on component in this scenario. To put this in OOP/PHP terms, consider the following example with the obligatory car analogy:
class Car {
public function start() {
$engine = new Engine();
$engine->vroom();
}
}
Car depends on Engine. Engine is Car's dependency. This piece of code is pretty bad though, because:
the dependency is implicit; you don't know it's there until you inspect the Car's code
the classes are tightly coupled; you can't substitute the Engine with MockEngine for testing purposes or TurboEngine that extends the original one without modifying the Car.
It looks kind of silly for a car to be able to build an engine for itself, doesn't it?
Dependency injection is a way of solving all these problems by making the fact that Car needs Engine explicit and explicitly providing it with one:
class Car {
protected $engine;
public function __construct(Engine $engine) {
$this->engine = $engine;
}
public function start() {
$this->engine->vroom();
}
}
$engine = new SuperDuperTurboEnginePlus(); // a subclass of Engine
$car = new Car($engine);
The above is an example of constructor injection, in which the dependency (the depended-on object) is provided to the dependent (consumer) through the class constructor. Another way would be exposing a setEngine method in the Car class and using it to inject an instance of Engine. This is known as setter injection and is useful mostly for dependencies that are supposed to be swapped at run-time.
Any non-trivial project consists of a bunch of interdependent components and it gets easy to lose track on what gets injected where pretty quickly. A dependency injection container is an object that knows how to instantiate and configure other objects, knows what their relationship with other objects in the project are and does the dependency injection for you. This lets you centralize the management of all your project's (inter)dependencies and, more importantly, makes it possible to change/mock one or more of them without having to edit a bunch of places in your code.
Let's ditch the car analogy and look at what OP's trying to achieve as an example. Let's say we have a Database object depending on mysqli object. Let's say we want to use a really primitive dependency indection container class DIC that exposes two methods: register($name, $callback) to register a way of creating an object under the given name and resolve($name) to get the object from that name. Our container setup would look something like this:
$dic = new DIC();
$dic->register('mysqli', function() {
return new mysqli('somehost','username','password');
});
$dic->register('database', function() use($dic) {
return new Database($dic->resolve('mysqli'));
});
Notice we're telling our container to grab an instance of mysqli from itself to assemble an instance of Database. Then to get a Database instance with its dependency automatically injected, we would simply:
$database = $dic->resolve('database');
That's the gist of it. A somewhat more sophisticated but still relatively simple and easy to grasp PHP DI/IoC container is Pimple. Check its documentation for more examples.
Regarding OP's code and questions:
Don't use static class or a singleton for your container (or for anything else for that matter); they're both evil. Check out Pimple instead.
Decide whether you want your mysqliWrapper class extend mysql or depend on it.
By calling IoC from within mysqliWrapper you're swapping one dependency for another. Your objects shouldn't be aware of or use the container; otherwise it's not DIC anymore it's Service Locator (anti)pattern.
You don't need to require a class file before registering it in the container since you don't know if you're going to use an object of that class at all. Do all your container setup in one place. If you don't use an autoloader, you can require inside the anonymous function you register with the container.
Additional resources:
Inversion of Control Containers and the Dependency Injection pattern by Martin Fowler
Don't look for things -- a Clean Code Talk about IoC/DI
I just followed the http://fabien.potencier.org/article/50/create-your-own-framework-on-top-of-the-symfony2-components-part-1 articles, and have some questions about the DI container.
Let's say I want to fire an event inside my controller, how would i get the dispatcher inside my controller?
I'm starting my test framework through
$c->get('app')->handle($request);
where 'app' is the Symfony\HttpKernel. How can i set the dependencies to the container? Let's say I have a view engine, defined in the container
$c->register('view.engine', 'Core\ViewEngine');
and I want to give that object, or resolve that object, inside my Controller to render some views. It's the same problem with the event fire, I don't have access to those values inside my controller ... How is a DI container supposed to work in situations like this?
Thanks!
There are different approaches. You might want to read through the silex documentation as a next step. In silex, the application itself is a DI container. You might also read through the introduction to Symfony 2 documentation.
The most straight forward approach (and the one used by S2 as a default) is to inject the DI container itself into your controller. The controller can then pull out services such as the dispatcher as needed.
A "better" approach is to inject the dispatcher along with whatever else the controller needs directly into the controller. It's "better" because the controller itself does not need access to the container. But it's more difficult since a controller often needs a number of services just to it's job.
==============================================
How would I inject the container in the controller though?
That is where looking at existing frameworks starts to come in handy. Remember that HTTPKernel is a component and not a framework. How you use it is up to you.
In Symfony 2 the app object is actually derived from Kernel and not HTTPKernel. The Kernel in turn contains an instance of HTTPKernel as well as an instance of the container.
There are several approaches you might take. There is no single "correct" one.
If you look into HTTPKernel::handleRaw you will find:
$controller = $this->resolver->getController($request))
You might make your own controller resolver object which would inject the container after creating the controller. Just one possibility.
i have been trying to get my head round factory patterns and dependency injection and i understand the concepts and basics behind both patterns and that there can be a slight cross over. But before i start coding it up, i just want to check my flow method would be correct.
My intended flow would be...
create a config file with all the properties needed for my 'core classes' in the format
$config['core.classname']['property_name']=$value;
create a factory class that will create an instance of all my core classes and run through the config file injecting the properties in to each class
when my app needs an instance of a class, it uses the factory class to clone the required class which has had its dependencies injected.
As i understand it this would decouple my core classes, allowing for them to be swapped in and out of my code easier.
What you are calling a 'factory' is really more of a dependency injection container. A factory traditionally only creates one type of object.
In general you should avoid creating any core instances until your app actually needs one. You may have 100 core classes defined of which any given app request might only need a couple.
In many cases your app will want to share the same instance or a core class so automatic cloning is probably not quite what you want.
Consider reading through the Service (what you call core) chapter in the Symfony2 framework package for ideas:
http://symfony.com/doc/current/book/service_container.html
How to solve the problem of composing a Controller class in PHP, which should be:
easily testable by employing Dependency Injection,
provide shared objects for end programmer
provide a way to load new user libraries
Look down, for controller instantiation with a Dependency injection framework
The problem is, that derived Controllers may use whatever resources the programmer wants to (eg. the framework provides). How to create a unified access to shared resources (DB, User, Storage, Cache, Helpers), user defined Classes or another libraries?
Elegant solution?
There are several possible solutions to my problem, but neither one looks to be a elegant
Try to pass all shared objects by constructor? (may create constructor even with 10 placeholders)
Create getters, settters? (bloated code) $controller->setApplication($app)
Apply singletons on shared resources? User::getInstance() or Database::getInstance()
Use Dependency Injection container as a singleton for object sharing inside the controller?
provide one global application singleton as a factory? (this one looks very used in php frameworks, hovewer it goes strongly against DI principles and Demeter's law)
I understand, that creating strongly coupled classes is discouraged and banished for :), however I don't know how this paradigm applies to a starting point for other programmers (a Controller class), in which they should be able to access shared resources provided to the MVC architecture. I believe, that breaking up the controller class into smaller classes would somehow destroy the practical meaning of MVC.
Dependency Injection Framework
DI Framework looks like a viable choice. However the problem still persists. A class like Controller does not reside in the Application layer, but in the RequestHandler/Response layer.
How should this layer instantiate the controller?
pass the DI injector into this layer?
DI Framework as a singleton?
put isolated DI framework config only for this layer and create separate DI injector instance?
Are you developing a framework yourself? If not, your question does not apply, because you have to choose from already existing frameworks and their existing solutions. In this case your question must be reformulated like "how do I do unit testing/dependency injection in framework X".
If you are developing a framework on you own, you should check first how already existing ones approach this issue. And you must also elaborate your own requirements, and then just go with the simplest possible solution. Without requirements, your question is purely aesthetic and argumentative.
In my humble opinion the simplest solution is to have public properties which initialize to defaults provided by your framework, otherwise you can inject your mocks here. (This equals to your getters/setters solution, but without the mentioned bloat. You do not always need getters and setters.) Optionally, if you really need it, you may provide a constructor to initialize those in one call (as you suggested).
Singletons are an elegant solution, but again, you must ask yourself, is it applicable in your case? If you have to have different instances of the same type of object in your application, you can't go with it (e.g. if you wish to mock a class only in half of your app).
Of course it is really awesome to have all the options. You can have getters/setter, constructors, and when initialization is omitted, default are taken from a singleton factory. But having too many options when not needed, is not awesome, it is disturbing as the programmer has to figure out which convention, option and pattern to use. I definitely do not want to make dozens of design decisions just to get a simple CRUD running.
If you look at other frameworks you will see that there is no silver bullet. Often a single framework utilizes different techniques depending on the context. In controllers, DI is a really straightforward thing, look at CakePHP's $helpers, $components variables, which instruct to inject appropriate variables into the controller class. For the application itself a singleton is still a good thing, as there is always just a single application. Properties less often changed/mocked are injected utilizing public properties.
In case of an MVC, subclassing is perfectly viable option as well: just as AppController, AppView, AppModel in CakePHP. They are inserted into the class hierarchy between the frameworks's and all your particular Controller, View and Model classes. This way you have a single point to declare globals for your main type of classes.
In Java, because of dynamic class loaders and reflection, you have even much more options to choose from. But on the other hand, you have to support much more requirements as well: parallel requests, shared objects and states between worker threads, distributed app servers etc.
You can only answer the question what is right for you, if you know what you need in the first place. But actually, why do you write just another new framework anyway?
Singletons are frowned upon when Dependency Injection is viable (and I have yet to find a case where a Singleton was necessary).
More than likely you will have control of instantiation of controllers, so you can get away with the mentioned $controller->setApplication($application), but if necessary you can use static methods and variables (which are far less harmful to the orthogonality of an application than Singletons); namely Controller::setApplication(), and access the static variables through the instance methods.
eg:
// defining the Application within the controller -- more than likely in the bootstrap
$application = new Application();
Controller::setApplication($application);
// somewhere within the Controller class definition
public function setContentType($contentType)
{
self::$application->setContentType($contentType);
}
I have made of a habit of separating static and instance properties and methods (where necessary, and still grouping properties at the top of the class definition). I feel that this is less unwieldy than having Singletons, as the classes still remain quite compact.
How about refactoring?
Granted that was not one of your options, but you state the code is a largely coupled class. Why not take this time and effort to refactor it to more modular, testable components?
As far as I understand, the Application class of yours should be the dispatcher. If so, I would rather use the controller constructor to pass an instance of the Application, so the controller would know who's invoking it. At later point if you want to have a different Application instance depending on whether the code is invoked from within CLI, you can have an ApplicationInterface which the Application\Http and Application\Cli would implement and everything would be easy to maintain.
You could also implement some factory pattern to get a nice implementation of the DI. For example, check the createThroughReflection method here: https://github.com/troelskn/bucket/blob/master/lib/bucket.inc.php
I hope this makes sense.
Regards,
Nick
You could also use a ControllerFatory in which you would give to your Application or Router/Dispatcher
Sou you could call $controllerFactory->createController($name);
Your Application would have no idea how to create your controllers the Factory would. Since you ca inject your own ControllerFactory in to your DI container you can manage all dependencies you want depending on the controller.
class ControllerFactory {
public function __construct(EvenDispatcher $dispatcher,
Request $request,
ResponseFactory $responseFactory,
ModelFactory $modelFactory,
FormFactory $formFactory) {
...
}
public function createController($name = 'Default') {
switch ($name) {
case 'User':
return new UserController($dispatcher,
$request,
$responseFactory->createResponse('Html'),
$modelFactory->createModel('User'),
$formFactory->createForm('User'),...);
break;
case 'Ajax':
return new AjaxController($dispatcher,
$request,
$responseFactory->createResponse('Json'),
$modelFactory->createModel('User'));
break;
default:
return new DefaultController($dispatcher, $request, $responseFactory->createResponse('Html'));
}
}
}
So you just need to add this factory in your DI container and pass it to your Application.
Whenever you need a new controller you add it to the factory and if new dependencies are required you give them to the factory through your DI container.
class App {
public function __construct(Router $router,Request $request, ControllerFactory $cf, ... ) {
...
}
public function execute() {
$controllerName = $this->router->getMatchedController();
$actionName $this->router->getMatchedAction();
$controller = $cf->createController($controllerName);
if(is_callable($controller, $actionName)) {
$response = $controller->$action(request);
$response->send();
}
}
}
This is not production code, I haven't tested, but this is how you decouple your controllers from your application. Notice here though that there is one bad coupling here because my controller return's a response and I execute the response in the App. But like I said this is just a small example.
It is usually a good idea to pass factories for Models, Forms, and Controllers to their respective parents, because you will end up loading all your object Graph at bootstrap time wich is really bad and memory consuming.
I know this answer was already approved, but it's my 2 cents on the subject
There is a good article on the subject
http://miller.limethinking.co.uk/2011/07/07/dependency-injection-moving-from-basics-to-container/