Accessing the DI container - php

I'm starting a new project and setting up the base to work on. A few questions have risen and I'll probably be asking quite a few in here, hopefully I'll find some answers.
First step is to handle dependencies for objects. I've decided to go with the dependency injection design pattern, to which I'm somewhat new, to handle all of this for the application.
When actually coding it I came across a problem. If a class has multiple dependencies and you want to pass on multiple dependencies via the constructor (so that they cannot be changed after you instantiate the object).
How do you do it without passing an array of dependencies, using call_user_func_array(), eval() or Reflection? This is what i'm looking for:
<?php
class DI
{
public function getClass($classname)
{
if(!$this->pool[$classname]) {
# Load dependencies
$deps = $this->loadDependencies($classname);
# Here is where the magic should happen
$instance = new $classname($dep1, $dep2, $dep3);
# Add to pool
$this->pool[$classname] = $instance;
return $instance;
} else {
return $this->pool[$classname];
}
}
}
Again, I would like to avoid the most costly methods to call the class. Any other suggestions?
Also, how do I access the DI class inside classes, for example, in controllers that need to access different models? Should I call it statically or pass it along each class that would require it? I don't think the last idea is feasible.
Thanks everyone.

[Before I start, let me say that I'm mostly a Java programmer - with only a little bit of PHP knowledge. But I'll simply try to get the most important concepts across without language specifics.]
Dependency Injection is based on two parts of code:
Construction
Execution
In its most extreme shape, there are no new operators to be found in the Execution part. All of them are moved into the Construction part. (In practice, this will be toned down.)
All of the construction happens - in the Construction part. It creates the graph of objects needed for Execution bottom up. So let's assume, it should construct A:
A depends on B, and
B depends on C.
Then
C is constructed first.
Then B is constructed with C as a parameter.
Then A is constructed with B as a parameter.
So C doesn't have to be passed as a constructor parameter to A. This small example doesn't illustrate strongly enough, how much this reduces the amount of objects that have to be passed around to quite a small number.
The Dependency Injector itself should not be passed into the Execution part. This is one of the basic mistakes everyone (including myself) tries to make, when they first come in contact with DI. The problem is, that this would completely blur the lines between Construction and Execution. Another way to say it is, that it would violate the Law of Demeter. Or in pattern speak: It would eventually "degrade" the Dependency Injection pattern to the Service Locator pattern. It's debatable, if this is really a degradation, but in any case it's usually not a good idea to misuse the Dependency Injector as a Service Locator.
So whenever you need to give one of your constructed objects the capability to produce other objects during execution, instead of passing the Dependency Injector, you would only pass simple Providers (a term used by the Java DI framework Guice). These are rather simple classes that can only create a certain kind of object. They have similarities with a factory.
First try to pass the required dependencies directly to the constructor.
So, to sum it up:
Build objects bottom-up.
Only pass as few dependencies as required to create an object.
Once your done, start executing.
During execution, you can still fetch newly created objects by using Providers.
But don't take it too far: Simple objects can still be created without a Provider :-)
And now, all you'll have to do is to translate this stuff into quality code. Maybe others can help you out with a few PHP examples.
Addendum: A little bit more about Providers
As noted above, the notion "Provider" (a specialized factory) is a bit specific to the Java DI framework Guice. This framework can automatically create a Provider for any type of object. However, the concept is generally useful for DI. The only difference is, that without the help of Guice or a similar framework, you'll have to write the Providers yourself - but that's quite easy:
Let's say, B depends on C.
If B just needs one fixed instance of C, then you don't need a Provider - you can simply construct B with the constructor argument C.
If B needs to create more instances of C during execution, then just write a class called CProvider with a get() method, that can create a new instance of C. Then pass an instance of CProvider into the constructor of B, and store the Provider in an instance field of B. Now B can call cProvider.get() when it needs a new instance of C.
Providers are part of the Construction code, so you're allowed to use new C(...)! On the other hand, they're not part of the Execution code, so you shouldn't have any execution logic there.
CProvider can be passed into multiple constructors of course. You can also write multiple versions CProvider1, CProvider2, ... - where each can construct different versions of C objects with different properties. Or you simple instantiate CProvider multiple times with different arguments.

You should look into using an IOC container to manage your dependencies for you. A good IOC container should take care of passing dependencies between dependent contructors for you.
There is an existing question asking about IOC container options for PHP.

It looks like you are trying to roll your own dependency injection container. Why not use one that already exists, like Symfony, Crafty or Sphicy?

Related

Dependency Injection Container and Collections

I have been searching for an answer in this topic but I haven’t been able to find a satisfactory one like in other topics, where the consensus is solid.
The situation
To keep things simple: I am implementing a custom Dependency Injection Container into one of my current projects (I know, I should use an already built one, but I’m doing it with learning purposes; so answers like ‘use this func of that container…’ are not useful) and I’ve stumbled a problem with instantiation of new elements inside a collection.
The problem
Imagine that I have a complex object, for example a car. This car has several dependencies (engine, axis, seats, airbags…) that have, at the same time, their own dependencies, and so on.
It is not a big issue to make the DiC (via autowiring or using a config file) build the object graph and inject all the dependencies with a simple line of code like:
$car = $container->get(‘car’);
The problem arrives when I build a CarCollection, which is a simple class that wraps an array of cars. The issue comes when I try to use a method that populates the collection with all the cars that exist in the database. It’s obvios that the collection should be able to create the Car objects on the fly when we call the “getAll” method from the database.
The code would be something like this:
public function populate(array $filters) {
$all_data = $this->dao->getAll($filters); // Call the data access object to query all cars.
foreach($all_data as $data) {
$new_object = $this->container(‘car’); // create a template object
$new_object->setData($data); // set the info.
$this->items[] = $new_object; // Add to the collection.
}
}
If car was not such a complex object it would be easier, because I could pass the car fqcn as a parameter for carCollection and use it in every iteration. But that’s not possible for a very complex object (or if I want to instantiate different sub types of the object - for example: lorry, pick-up, van…- depending on information from the database).
The question.
Regarding the collection being aware about the container: does not it break the purpose of the DIC phylosophy?
I guess not on one side, because I am using PSR\Container to type hint the container I pass to the collection (which loosens the coupling). But it breaks the idea that the container should not be coupled with the domain model at all.
The only alternative that I have thought about is substituting the creation of one new object for each iteration with a cloning from a prototype object that lives in the collection as a property. But we all know cloning in php can get really tricky and very difficult to debug (Or worse: very difficult to even know that there is a problem going on).
Similar issue.
PS: I have the same problem when I try to do lazy loading using Porxy objects: I need the proxy objects to have access to the container if I want to instantiate the full object later, which also breaks the principles of a DiC.
Thank you all.
I think the core of your issue comes down to this:
The issue comes when I try to use a method that populates the collection with all the cars that exist in the database.
The composition of object graphs of application components should be independent of any I/O, as described here and here by Mark Seemann. This means that the structure of those object graphs can't (and shouldn't) change based on changes in your database.
It seems to me that your Car object is a Domain Object, rather than a (Domain) Service. It would, therefore, be better suited to return a collection of Car instances from a service, rather than injecting the collection directly into one of your application components.
I need the proxy objects to have access to the container if I want to instantiate the full object later, which also breaks the principles of a DiC.
It's generally considered to be a bad practice to let application code depend on the DI Container. This a a pattern known as the Service Locator anti-pattern. There are many reasons why Service Locator is considered to be a bad idea, but it's important to understand that the list of downsides of Service Locator do not apply when the DI Container is used in the application's startup path (a.k.a. the Composition Root). A DI Container used within the Composition Root, is not an implementation of the Service Locator anti-pattern.
When your proxy classes are defined within the Composition Root, it's perfectly fine to let them depend on the DI Container and you won't violate any software principle or practice.

Dependencies - Injection vs new Instances

I'm currently using Laravel and have a pretty good general grasp now on how the dependency injection and service container works now. I see it working very well when programming to interfaces, but what about concrete classes?
I utilize a service layer between my controllers and models. The point of the service objects was so that I could easily reuse their methods elsewhere, like in a different controller. But there are cases where I also need to use a service inside another service.
So I've been using the constructor for the dependency injection inside my services. The issue I kind of see is that sometimes I only need a service (inside one of my other services) for 1 method. So doing it in the constructor makes it rather large. On the other hand, since I've been setting these parameters in the constructor, I can't simply new-up an instance on demand, since it requires those parameters. For example, let's say I have an OrderService class, and for the constructor, I see two ways I can go about it:
public function __construct(FileUploadService $fileUploadService)
{
$this->fileUploadService = $fileUploadService;
}
or
public function __construct()
{
$this->fileUploadService = new FileUploadService;
}
I've mostly been doing it the first way, but have been thinking about the second. If I ever needed this OrderService somewhere else in the app, I can't simply create a new instance since it relies on the FileUploadService, unless I create a new instance of that too. But you can see that it will start to cascade without the dependency injection, because what if the FileUploadService depends on something also? It's just easier to resolve it out of the container.
Maybe there's something I'm missing, because it almost feels like a catch 22 in some ways. I'd like to note that a majority of these classes I'm injecting are concrete classes, so I don't need to swap them out at any particular point.
I've thought about just creating a new instance in the constructors for each service I need, that way I can also new-up the instance without providing parameters. But I like to follow best practices, so I was wondering what other experienced developers thought about this.

IoC Container and global variable

I see advise from a lot of people teach not to use global variable/singleton/static class and move to use of a iOC container, for example, in PHP larvel framework, it is
App::bind('foo', function($app)
{
return new FooBar;
});
$value = App::make('foo');
instead of
$value = new FooBar;
But to me, the App::bind itself is a static method and cannot be replaced easily.
So, can I say, the iOC (at least in PHP), is just remove the number of hard coded variable and minimized to one, which is the service locator, and it cannot be further reduced, right?
App::bind is not a static method, this is it's signature:
public function bind($abstract, $concrete = null, $shared = false)
(found in /vendor/laravel/framework/src/Illuminate/Container/Container.php)
Laravel uses Facades, which, while they look like they are calling a method statically, actually instantiate an object under the hood and then call an instance method on that object. While Laravel does use some static methods in it's models, the App object itself is actually a facade. You can see a list of the built in facades if you look in /vendor/laravel/framework/src/Illuminate/Support/Facades/.
So, can I say, the iOC (at least in PHP), is just remove the number of hard coded variable and minimized to one, which is the service locator, and it cannot be further reduced, right?
You are seeing this correctly, but you can actually reduce the number of hard coded variable to 0.
The problem here is not App::bind() because it's configuration. Configuration has to be coupled to some kind of system because that's where you set all the details. That's OK here.
But having App::make() all over your codebase is the problem. You want to write reusable code. You don't want your model to be coupled to Laravel for example. The fact of calling the container is called the service locator pattern (because you locate services with the IoC).
This is an anti-pattern, because, as I've said, you are coupling your code to the container.
On the other hand, there is the dependency injection pattern which is better. Dependencies are injected in your classes, but you don't care how. This is just pure PHP, completely decoupled from any container.
I invite you to read stuff on the subject, Laravel can actually be used with full dependency injection (no static calls to Facades). Here is an article on the subject: Using Dependency Injection and IoC in Laravel 4 controllers
Howard, I think the context you might be missing is why people say
global variable/singleton/static class
are "bad". The reasons you don't want global variables in your application is, relying on global state is going to lead to pain. When you're modifying values that other parts of the program also have access to, it's likely two parts of a program are going to access that same variable and unexpected "bad" things will happen. Singletons and static classes are often lumped in with global state, because they're globally available things.
So yes, your statment
is just remove the number of hard coded variable and minimized to one, which is the service locator, and it cannot be further reduced, right
is accurate, but more than that a service container (if services are being created correctly) gives you global access to a thing-to-do-a-job, but is makes it hard/impossible to use that global thing-that-does-a-job to store global application state.

Why use Zend_Registry instead of the Singelton pattern?

Why should I use Zend_Registry instead of the Singleton pattern?
My coworker and me recently had a discussion about this. His point was that we should use Zend_Registry for all consistent objects, but I wanted to use the singleton pattern, since Zend_Registry just does the same, but wrapped.
I have a problem with code like this:
$list = Zend_Registry::get('database')->getList($sql);
Since theres a chance that database isn't in Zend_Registry. In cases of lazy loading, I would have to make my own registry with information about specific objects in my system. Like if the database takes specific parameters on loadtime, then it would have to know this.
I would instead use getInstance and then all the code would reside in the same object. Does that make sense?
Even though you phrased your question as an either/or, might I suggest a third alternative?
I try to avoid both singletons and Zend_Registry wherever possible, since they function, in effect, as globals. When a segment of code can reach into the global ether - via a call to a singleton or a global registry - to get something it needs, it creates a hidden - or at least, a non-explicit - dependency that makes things harder to debug and unit-test.
In contrast, I try to follow dependency injection advice, paraphrased as: "Give a component what it needs. Don't make it find what it needs."
I find that for most entities for which I might feel I need a registry/singleton - db connections, loggers, etc - I can create them at Bootstrap, store them in the Bootstrap registry and inject them into my controllers, usually during init() using $this->getInvokeArg('bootstrap')->getResource('myResource'). Only controllers reach back into the Bootstrap. Then, any models or services that need these dependencies get them passed-in explicitly by the controller, either via constructor or by setter injection.
A hybrid approach to which I do sometimes fall back is to design my service/model classes with getters/setters for these dependencies - getDbAdapter() and setDbAdapter(); getLogger() and setLogger(), etc. The getter lazy-loads from the global registry - whether some singleton or by Zend_Registry, throwing exceptions when they are not where I expect them to be. In that sense, it is similar to what you are suggesting. It does violate the purist dependency injection philosophy. But at least the presence of the getter/setter methods explicitly demonstrates that there is a dependency and allows me to mock it out or to provide non-default implementations.
It does for simple blog or something. Otherwise you're stuck with only one DB instance. And that's NOT what you want in the long run. You may want to connect to other server (to log errors to central db, to import products from someone, ...) or connect as different user (for security reasons - you don't want your API to have access to admin_users table, but you still need to connect to it to check if user is valid in the first place).
You can do one-purpose registers (My_Db_Admin, My_Db_ReadOnly, ...) but that does not make much sense to me. Using registry you're not stuck with one instance. You can create one outside registry and work with it for a while and then trash it ;)

ServiceLocator and the Open/Closed Principle

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.

Categories