I've been using the DI concept for some time now, but now I'm starting to use a dependency injection container (DIC). Although one thing isn't clear for me.
In my DIC I keep (for example) a Config object and Request object. I understand that these objects in a request scope (The same instance is used each time you request it from this container) remain the same. But this only happens when I re-use the same instance of the DIC.
How should I pass the DIC arround my classes? Say that I want to use it in my Router class, do I need to pass it in the constructor of my Router class? But the Router class is created in another class, and that one should also already have this DIC object.
Or should I create a singleton of this DIC?
Don't go the Singleton route. It effectively takes all the advantages the DIC gives you. Usually you pass the container in constructor, or as a method parameter where applicable.
Yes, this requires you to put an extra effort in passing the container object around your application, but as a result your code reflects well that these classes are dependent on this object to work.
Related
In the service container of Laravel, I can bind both singleton and instance. From the Laravel doc:
Binding A Singleton
The singleton method binds a class or interface into the container that should only be resolved one time. Once a singleton binding is resolved, the same object instance will be returned on subsequent calls into the container:
$this->app->singleton('HelpSpot\API', function ($app) {
return new HelpSpot\API($app->make('HttpClient'));
});
Binding Instances
You may also bind an existing object instance into the container using the instance method. The given instance will always be returned on subsequent calls into the container:
$api = new HelpSpot\API(new HttpClient);
$this->app->instance('HelpSpot\API', $api);
Q1) So what is the difference between the two concepts? Can I guess that for singleton binding, Laravel upon first request builds the object itself through internal service container mechanism and then supplies it on subsequent calls whereas in the case of instance binding, service container is explicitly given an already built object which it supplies on every request?
Or is there any other explanation?
Q2) Why do we need both binding options?
Difference between singleton and instance
The two concepts are very much alike. The only difference is, indeed, the fact that you either pass in a class/interface or an object.
Singleton docs:
The singleton method binds a class or interface into the container that should only be resolved one time. Once a singleton binding is resolved, the same object instance will be returned on subsequent calls into the container
Instance docs
You may also bind an existing object instance into the container using the instance method. The given instance will always be returned on subsequent calls into the container
Why do we need both?
The answer to this question is probably rooted in the Laravel philosophy. From what I see in most of the features Laravel provides, there's more than one way to solve an issue. It feels like this is one of those as well. There's slight differences which might make singleton or instance usage preferable in some cases.
Singleton usage
The use of singleton will help keep your application light, as these classes/interfaces do not get created if they are not used.
Instance usage
In some cases you might've already created an object, which you still need to inject into other places. That's where instances comes in.
Additional to what #PtrTon said, the difference is also in the time, the instance is created. Using an instance, the instance is—of course— created before passing to the service container, meaning it's created quite early. Whereas using a singleton, the instance is created the first time, the binding is resolved as far as I know which can be a considerable amount of time after the example where you pass an instance.
When I first saw dependency injection components like PHP-DI, Symfony2 DI, etc., I though, there is a way to automatically inject instance of any class to any just with one instantiation.
So
1. Create instance in root class like $foo = new Foo()
2. And then I can use this instance in any object (like global singleton) without passing reference to constructor or method of the class I want to call from.
But I found out, that basicly I can use Dependency Injection in 2 ways
1. Passing the reference of the instance to constructor
2. Creating container where all objects are located. This container could be injected to other classes, but "This is not recommended".
As both ways can be easily done in pure PHP, the first is clear, the second could be solved with static properties, so why to use PHP-DI or Symfony2 for this work?
Why should you use Dependency Injection over the Singleton pattern?
Let's assume we have a Singleton object named DatabaseConnection which wraps a connection to a MySQL database for us and does some other neat things, who knows. Because reusing code is a good thing, we use this object in a lot of projects.
What if at some point we decide to switch one of our projects from MySQL to another database product? We would have to modify every place where we call the DatabaseConnection object and replace it with our new implementation. Or, we could modify the class itself -- but we still want to use the original one with other projects, so we end up with two implementations with the same name which is just asking for trouble, really.
And what about unit tests? We do those, of course, because we are good developers! But if we unit test a function that uses the database, we don't want the test to actually rely on the database or even change things there. There's no way to replace the DatabaseConnection with a mock object (that just returns static data) because our project is tightly coupled to it.
That's what Dependency Injection does: It helps to prevent tight coupling. If we inject the connection with $someObject->setDatabaseConnection($databaseConnection), we can inject any object there that behaves like the original one. We can inject mock objects, alternative implementations or extensions that inherit the original class.
Now a Dependency Injection Container is just a nice helper to manage object instances and their dependencies more easily, but it's not needed for doing Dependency Injection.
You may access the (let's say) Doctrine service inside the controller, using:
$d = $this->getDoctrine()
now I want my controller to call another function (in another class) and I want that class to have access to all services. Is that possible without passing the services as variable?
You have to inject dependent services to your class or method. If you were thinking about some global object you might access everywhere than it's not the right way to go (and you can't actually access the container this way). You'd miss the whole point of dependency injection.
You can inject the services to your class two ways:
Manually
Let DIC do it
First solution requires you to pass the dependency yourself either way (constructor, setter, method).
The later solution means you define your class as a service and let container construct it and inject the dependencies. It can only be done if you can delegate object creation to DIC. It cannot be done with Entities for example.
Be careful with injecting whole container. It's not the best practice. You'd introduce dependency on a whole container which might have different services depending on the configuration. Dependencies wouldn't be clear.
I'm trying to pass the entity manager to a service but havent find a correct way yet. I want to complete remove the em from the controller so thats why I'm finding another way.
I was thinking of this options:
1. I could save it in the registry and then try to access it from the service object. can I access the registry from there?
2. Inject the em to a static variable of a base class for the services in the bootstrap.
What is the correct way yo do it?
thanks
I think generally the best way to do it is to pass the entitymanager as an argument to the constructor.
This allows you to easily replace the entitymanager for example when doing unit tests, and unlike your approaches of 1 and 2, it does not depend on behavior in a base class or global data (the registry is a lot like a global variable)
What you could do to avoid touching the EM in your controllers is using a dependency injection container, such as the one in Symfony2 or the one in ZF2 (not sure if that component is very stable yet).
Another perhaps slightly simpler approach would be to have a sort of a "service locator" object, which you would use in the controller to get instances of your services. You could initialize the locator in your bootstrap with the services, or perhaps with a factory class which creates them.
In any case you will probably require at least some kind of an intermediate object in the controller. Personally I don't really see an issue with simply using the EM itself, unless you have some other reasons besides just not wanting to.
There's nothing wrong, IMO, with letting your controllers know about the EM. I typically use a Zend_Application_Resource to bootstrap Doctrine. That resource facilitates a bootstrap resource called "doctrine" which has an EM available. The abstract controller implements and em() method, which returns the EM.
When instantiating service classes, the constructor simply injects the EM via a call to $this->em() at constructor time.
This is nice, as many times, simple controller actions don't need any special service class, but can instead get away with doing $entity = $this->em()->getRepository('Some\Entity')->find(1); In those cases, I don't see any reason for additional redirection via a service class.
I know that Singleton pattern is bad because it uses global state. But in most applications, you need to have a single instance of a class, like a database connection.
So I designed my Database object without using the singleton pattern but I instanciate it only once.
My question is, how can I access my object in the low level classes (deep in the object graph) without passing it all over the place?
Let's say I have an application controller which instanciates (ask a factory to instanciate it actually) a page controller which instaciates a User model which requires the database object.
Neither my app controller nor my page controller need to know about the database object but the User class does. How am I suppose to pass the object to it?
Thanks for your time!
Consider using a global container:
You register the objects that are indeed relevant to the several subsystems of the application.
You then request that container those objects.
This approach is very popular in dependency injection frameworks (see Symfony DI, Yadif).
Singleton is bad, no doubt about it.
In the case you describe, the database object is an implementation detail of the User object. The layers above need only know about the User, not the database object.
This becomes much more apparent if you hide the user object behind an interface and only consume that interface from the layers above.
So the page controller should deal only with the interface, not the concrete class that depends on the database object, but how does in create new instances? It uses an injected Abstract Factory to create instances of the interface. It can deal with any implementation of that interface, not only the one that relies on a database object.
Once more, you hide the page controller behind an interface. This means that the concrete implementation's reliance on the Abstract Factory becomes another implementation detail. The Application Controller only consumes the page controller interface.
You can keep wrapping objects like that like without ever needing to pass around instances. Only in the Composition Root do you need to wire all dependencies together.
See here for a related answer with examples in C#: Is it better to create a singleton to access unity container or pass it through the application?
The way I've always accomplished this is to implement a static getInstance function that will return a reference to the single instance of that class. As long as you make sure that the only way you access the object is through that method, you can still ensure that you only have one instance of the singleton. For example:
class deeply_nested_class {
public function some_function() {
$singleton = Singleton::getInstance();
}
}
There are two main objects involved in loading/saving a user using the database: the user and the repository.
You seem to have implemented the functionality on the User, but I think it belongs on the Repository. You should pass the user to the Repository to save it.
But, how do you get hold of the Repository? This is created once at the top level and passed into services that need it.
The construction dependency graph and the call dependency graph are not the same thing.
Given the example you outlined, you are almost there. You are already using a factory to instantiate your page controller, but your page controller is instantiating the users directly and as your User needs to know the database.
What you want to do is use a factory to instantiate your User objects. That way the factory can know about the database and can create User instances which know about it too. You will probably be better off making interfaces for all the dependencies, which will help with testing and will mean your code is nicely decoupled.
Create an IUserFactory which creates IUser implementations and pass this into your PageControllerFactory, then your ApplicationController only needs to know about the PageControllerFactory, it doesn't need to know anything about the IUserFactory or the database.
Then in your application start up you can create all of your dependencies and inject them in to each other through the constructors.