So in Silex, I am attempting to get the $app parameter out of my controller actions and just pass in the dependencies that are relevant to the controller/action.
Generally my controllers have these shared dependencies:
Template engine
Session provider
Translation provider
URL generator
Validation provider
I've got a base Controller class to accept these on the constructor by default. The controllers inheriting from it also end up taking those parameters as well. Additionally they take other parameters, such as an object repository/store (such as a user repository in an authentication or user controller).
I end up registering the controllers in Silex with at least 5 parameters to the constructor when it seems like I don't see a lot of that in other applications. Feels like I'm doing it wrong.
I also realize that I'm complaining about the same thing that the Pimple DI container "fixes," but using it also seems not quite true to the DI philosophy.
My question: Is there a better way to do what I'm doing?
Yes there are alternative solutions.
The first one is to "group" your parameters into new classes like ControllerUtil or things of the sort. That's not always easy or possible though, so I'm not a particular fan of that.
Benjamin Eberlei explains this approach in this blog post: Extending Symfony2: Controller Utilities
The second is to use alternative to constructor injection, like property or setter injection. This is not as clean as constructor injection, but it is extremely practical.
Given controllers are generally not the kind of components you want to reinject, reuse or unit-test a lot, so this is an acceptable compromise IMO. I've been using that method for about a year and I can't go back.
Here is a related blog post I wrote on that subject: Controllers as services?
hope some of you can give me a hand with this.
Im working in a project using Codeigniter 2 and Doctrine 2, everything is working ok but I have some "sanity" issues i would like to fix.
The main problem I have right now is with persisting the entities.
In a normal MVC the persistance should be in the Model, but now that I only have Entities and Repositories and i dont have the so called "Models", I'm putting all of this code in the controller making them huge and intimidating :(
I've read on some places that the best approach for this is to have a "Service" layer between the Controller and the Entities, but I haven't found a good way to do this in Codeigniter due to is hard classic MVC pattern.
So im asking for some advice in how to aproach this.
Any of you guys is having the same problems?
I found a solution for my problem, hope it works for some of you.
I'm using Joel's Verhagen integration of Codeigniter 2 and Doctrine 2, you can read his article for more detail "http://www.joelverhagen.com/blog/2011/05/setting-up-codeigniter-2-with-doctrine-2-the-right-way/"
In simple words what I'm doing is using Codeigniter's Models as a Service layer.
This was the cleanest approach that i could find, mainly because all the "wiring" is already done by Codeigniter, so I didn't have to make anything else :D.
I had to make some modifications to the folder structure of Joel's implementation, that way i can use CI's models and still using his Doctrine code.
So I moved everything from inside the folder "models" to a new folder called "entities" (I know it might not be the best name, but it works :P).
Then I changed all the references to the new folder and checked that everything worked.
That's it, now i have my "service layer" workign and my code is a lot more cleaner.
If some of you need help with this, please feel free to ask me.
Was in the same boat a while back. Ended up not using Doctrine's ORM, but basically you're right - you need a "service layer" for anything that isn't directly modeled via Doctrine's entities and repositories.
The way I do this creating a namespaced folder in /application/ for my project code. I then used Doctrine Common's class loader to recognize that folder as the namespace. For example /application/Acme/Authentication.php contains:
namespace Acme;
class Authentication {
//Do Doctrine queries in various methods here
}
Doctrine's class loader uses SPL (spl_autoload_register or something) internally. What that means is that you can fully use PHP 5.3 namespaces. You then have all the fun trials and tribulations of dependency injection for accessing the doctrine dbal inside this service layer. Your controllers will then use this "service layer" directly. Like I said, in my case I decided not to use Doctrine's ORM - so I'm using CodeIgniters ActiveRecord database classes inside my "service layer". Rather than using $this->CI =& get_instance() ... I'm providing the database access into the constructors using a DI container.
For example in my auth/login controller action I may have
function login() {
$user = $_POST['u'];
$pass = $_POST['p'];
$auth = new Acme\Authentication($this->db); //or use a DI container
$user = $auth->authenticate($user, $pass);
....
}
How do I use a component that I created in cakePHP inside one of my model classes? Is this possible?
If so, please let me know how I can do so
It is possible but pretty bad practice in a MVC framework. You should re-think and re-organize your code if you think you need to use the component in a model because something is cleary wrong then.
A component is thought to share code between controllers, only between controllers.
Components in CakePHP 1.3
Components in CakePHP 2.x
Components in CakePHP 3.x
To share re-usable code between models it would be a behavior. For a view it would be a helper.
If you have some really generic code it should be a lib or put it in the Utility folder / namespace or create a new namespace. Check the existing classes there to get an idea what to put in there.
No code was provided so it is not possible to give any real recommendation on how to refactor it. However the way you want to use the existing code won't work in the MVC context, so time to rethink your approach of whatever you try to do.
It is possible to use a component inside a model (but I cannot comment if this is a recommended or a best-practice).
Inspired from original source, an example to use a component called ‘Geocoder’ in a model:
App::import('Component','GeoCoder');
$gc = new GeoCoderComponent(new ComponentCollection);
Then you can use $gc to call the functions of the component.
--
P.S.: I do not want to encourage bad programming practices, but sometimes the pressure of deadlines (in real world projects) may force a developer to make such decisions.
#AD7six
// Use anywhere
AuthComponent::user('id')
// From inside a controller
$this->Auth->user('id');
From the cake PHP documentation they provide AuthComponent::user('id') so that it can be used in places other than a controller.
Maybe I need a bigger hint, but why shouldn't my model be able to access ACL information ?
I'd like to:
Make commonly required services visible to all classes that need them,
with a minimum of boilerplate, and
without sacrificing testability!
It's a small project and I think DI might be overkill, but maybe I'm wrong? Anyhow, I have been focusing on the ServiceLocator pattern as described by Martin Fowler
In a client class' constructor, I have something like this:
this->db = Locator::getDb();
this->log = Locator::getLogger();
Then the rest of the class' methods access the service through those member attributes, e.g.:
this->fooModel = new fooModel(this->db);
fooItem1234 = this->fooModel->findById(1234);
However I would also like this level of visibility for "model" objects (like fooModel above) because they are accessed from several different places and there is no need to have more than one instance.
So my initial thought was to extend Locator to have a ::getFooModel() but now it seems I'm violating the Open/Closed Principle, since I'll have to modify Locator every time I introduce a new model class.
To satisfy OCP, I could use the Dynamic Service Locator (also described on Fowler's page) however I'm not totally sold on this for the same reasons as him, i.e. it's not explicit enough.
Another solution would be to just make all my models' methods static. So:
fooItem1234 = FooModel::findById(1234);
I like this because it's zero boilerplate. I can just create a new model class and start calling it from anywhere with a single line. But now the model depends on Locator to find its DB connection and I'm not sure how I feel about that. For one, if I ever needed to have two fooModels open on separate database connections, it would be a mess and/or impossible. That said, I don't actually need to do that currently so this option seems a little tempting.
Finally, there's DI. But like I said above I think it might be too much for this little project.
Conclusion: I'm a little stuck here and would appreciate some advice from the gurus of StackOverflow!
Why do you think that DI is overkill for your project? DI patterns such as Constructor Injection is way simpler and cleaner than Service Locator (which I consider an anti-pattern).
I consider Service Locator to be an anti-pattern since it is totally opaque to the user of the API which dependencies need to be in place; thus, one could easily invoke methods on your objects in a context where the Service Locator would throw, and the API gives you absolutely no clue that this is the case.
You don't need a DI Container to use DI. If just have a simple project, you can use what is known as Poor Man's DI where you wire up dependencies manually.
... and there is no need to have more than one instance.
You're mixing apples and oranges. The fact that you only need one instance of a class for an application, is not the same thing as it being a good idea to make that instance globally available. With DI you don't change the cardinality - there is still just one instance. What you change is the scope of variables that address said instance. There's a difference.
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/