Composing a Controller class with Dependency Injection in PHP?

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 Imho 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?

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. Imho 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?

Yes, I'm building, trying out a simple component based framework, I needed the exact push, your answer gave me.. Also, as I stated before, a lot of frameworks solve these by utilizing Singletons, but I want to evade global state as much as possible (components should be easily replaceable). Will upvote next day (ran out of votes :)). Thank you for your time – Juraj Blahunka Feb 14 '10 at 21:01.

Maybe you can look into this little DI library. Very simple to use and testable gabordemooij.com/harbour.

Thanks for recommending, however as I can say from the page, this library is pretty young, the Documentation page is still under work, I'm not sure if this is a stable and viable solution – Juraj Blahunka Feb 8 '10 at 13:32.

Harbour is my project but I have a track record of quality maintenance. I also wrote: redbeanphp.com, you can be assured that Harbour will be maintained well and documented well. So don't worry.

Also, while it's young and yet undocumented it's also extremely simple; only 3-4 classes and less than 600 lines of code I guess. I plan to release it officially in about two weeks.

Looking forward to it.. I have tried RedBean in Summer 2009 and was amazed by its functionality and simplicity :) – Juraj Blahunka Feb 10 '10 at 9:09 I consider using a DI framework, hovewer I still don't know, what is the best solution to create / compose such a coupled class, with lots of dependencies – Juraj Blahunka Feb 10 '10 at 11:49.

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?

Good point, however I don't know whether it's good idea, as by breaking up the Controller class, the MVC pattern would shatter.. – Juraj Blahunka Feb 11 '10 at 19:54 You'd still have a controller as is, but the controller would be refactored so that the internals of that class are changed. The public interface to your controller should remain unchanged, it just the code internally will be split up. Granted this is speculation on what your code looks like, but that's what I'd do.

– Finglas Feb 11 '10 at 20:45 Can you point me to some studies or blogs, where this is discussed? – Juraj Blahunka Feb 12 '10 at 7:10 Check out the Single Responsiblity Principle (Part of SOLID). To summarise, a class should do one thing and one thing well.

Not multiple jobs, which is what your controller sounds like it's doing now. – Finglas Feb 13 '10 at 10:46 I still get back to using DI, passing loader objects as param, which can load other libs for end user (easy to mock and test) – Juraj Blahunka Feb 14 '10 at 12:03.

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.

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.

This doesn't look like a solution, for which test writing would be easy.. The ::setApplication will create a global state for all Controllers and I don't believe this is the way to go.. – Juraj Blahunka Feb 6 '10 at 16:48.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions