The SitePoint Forums have moved.

You can now find them here.
This forum is now closed to new posts, but you can browse existing content.
You can find out more information about the move and how to open a new account (if necessary) here.
If you get stuck you can get support by emailing forums@sitepoint.com

If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

Even if it is as close a rip of the Ruby as I can get in a first try. I think PHP dulls the mind, and that Container should be a singleton. (In the Ruby version there is a ContainerRegistry, and it is the singleton. What's the code of the day for making singletons in PHP4/5 = PHP0.8 as I think I'll call it?)

Agreed. It's simple and effective. I don't think it's appoipriate to label it DI though. It's more of a registry of factories, and thus a ServiceLocator. To call it DI, I would think that the DI would need to be more intelligent. In this implementation, the smartness is handcoded by the programmer, who write the factories.
I may be on thin ice here - the boundries between the various patterns are really fuzzy.

Incidentially, I created an implementation which very much resemble that code, recently. I handled the singleton-strategy by simply writing a static class, which is the userland-api to the locator. This would then fetch the needed factories from a registry. The registry itself can be replaced at runtime, allowing for some flexibility. (useful during testing for example)

It's simple and effective. I don't think it's appoipriate to label it DI though. It's more of a registry of factories, and thus a ServiceLocator. To call it DI, I would think that the DI would need to be more intelligent. In this implementation, the smartness is handcoded by the programmer, who write the factories.

And in Java DI containers, the factories are generated by inspecting the component to be instantiated. I think thats mostly a convenience and not essential to the pattern. The feature that makes it DI is that the component receives instances of the objects that it depends on from a third party assembler object. It may be "dumb" DI, but its still DI.

Agreed. It's simple and effective. I don't think it's appoipriate to label it DI though. It's more of a registry of factories

I'd say that a "registry of factories" would be a good description for a ServiceLocator or DI, but not good enough to distinguish them. The defining difference (as has been said a couple of times in this thread) is that a ServiceLocator is used to locate dependencies (== services which are depended on) by the object which needs them, whereas in Dependency Injection the dependencies are provided to the object by something external.

In the first case, the "registry of factories" are only responsible for constructing the dependencies, in the second case (when using constructor injection) the "registry of factories" is responsible for constructing the object itself too, which is what the Logger and Application functions do.

With setter injection you could pass in instances instead of having the DI construct them, here's some code to inject dependencies using setters:

(You'll need to add some more code to manage storing instances or to interact with a separate registry to make it useful though.)

Originally Posted by kyberfabrikken

In this implementation, the smartness is handcoded by the programmer, who write the factories.

Yep, I'm with you on that, it isn't particularly flexable, which is why I made this post. There, you can replace the Container class instance easily (it is in the second block of code, below the fold.)

The feature that makes it DI is that the component receives instances of the objects that it depends on from a third party assembler object. It may be "dumb" DI, but its still DI.

In that case, passing an object is DI. While that may well be true in the strictest sense of the word, it doesn't describe the pattern, which pico et al follow. Perhaps we should destinguish between DI as a general technique and ComponentContainer as a specific way of archiving it. ServiceLocator being another way to do the same thing.

Originally Posted by DougBTX

Yep, I'm with you on that, it isn't particularly flexable

On the contrary - it's extremely flexible, but at the cost of automation. Combining it with a default automated behaviour solves this problem somehow. There'll still be redundant code in the specialcases, but that may be an acceptable tradeoff.

The feature that makes it DI is that the component receives instances of the objects that it depends on from a third party assembler object. It may be "dumb" DI, but its still DI.

Disagree. That statement describes a builder pattern and factory pattern combined only. I think DI is a combination of things and it's this combination that makes it qualitively different. Without the autowiring, the container becomes more of a builder becuase you need to give explicit instructions. However, it can still automatically apply decorators and select from a hiearchy of choices. That's a very specific smart builder.

Of course it now means that I have to define it and if I do, I will take something for granted and miss that out to . So I'm not going to . Here is a partial list of important properties...
1) Autowiring (automatic dependency instantiation)
2) Smart lifecycle instantiation (singleton, sessions, etc)
3) Hierachical service location from preregistered descriptions (usually just a class name with recency of registration)
4) Invisible to components (uses setters, constructor)

I'd say that the first three are implementation details, and only the fourth distinguishes DI.

From the Fowler article:

For this new breed of containers the inversion is about how they lookup a plugin implementation. In my naive example the lister looked up the finder implementation by directly instantiating it. This stops the finder from being a plugin. The approach that these containers use is to ensure that any user of a plugin follows some convention that allows a separate assembler module to inject the implementation into the lister.

Forgive me if I misunderstand the previous conversation regarding DI::get(...) versus $di->get(...). I don't think i've ever used the static method call singleton where I haven't later regretted it. How about $this->get(...) instead?

Forgive me if I misunderstand the previous conversation regarding DI::get(...) versus $di->get(...). I don't think i've ever used the static method call singleton where I haven't later regretted it. How about $this->get(...) instead?

Forgive me if I misunderstand the previous conversation regarding DI::get(...) versus $di->get(...). I don't think i've ever used the static method call singleton where I haven't later regretted it. How about $this->get(...) instead?

Unfortunately, as Douglas explained, the "$this" scope is not available from within the function, although theres the "$di" parameter in case you want to make a traditional-style method call. Either way you are bound to either the name of the class or the name of the parameter, so it's kinda six on the one hand or a half a dozen on the other. I favor this style:

PHP Code:

DI::register(
'store',
'return new MyStore(DI::get("gateway"));');

My reasoning behind it being that if you ever have to change the name of the singleton class, all the changes are centralized on the same line.

Originally Posted by sweatje

Now one might argue that a singleton DI containter with a "clear()" method would be enough, but I somehow feel safer and more confident of less potential test interference with separate instances.

(sorry that it took me so long to reply to that, Jason, this thread is like a part time job )
As Jason and others have pointed out, it might be a good idea for some to allow separate instances of the container/injector to be created, and do away with the singleton idea. Jason gives the example of unit testing, where you obviously want a set of mock objects that are not quite the same "services" you define in other parts of your application. For an instance, within your test class, you may want to use the container to retrieve an instance of the "Test" database connector as opposed to the live ones in order to do your testing.

I know that I am in the minority in this opinion, but, personally, I would probably tackle the issue from a different angle, while still using a singleton registry. I would either do something like this in my configuration script:

Which allows you to replace any aspect of your registry to inject it with mock objects. At the same time you get to see at a glance and from one single place what each "service" or "component" is made up of.

Additionally, this is also an aspect of flexibility that other DI implementations do not have: to allow for different named services that may share the same interface dependencies, but do not neccesarily have to be composed of the same classes. Unless I am mistaken, because of its reliance on interfaces, Pico does not allow you to create two different named components that share the same interface. Since interfaces are the "lookup key" within pico, you can only get either the one or the other. Personally, I think this is very limiting, specially for testing purposes. There are ways around it, as seen here in this portion of Jason's example:

But then you have to mess with unregistering and re-registering components, because Pico limits you to "one interface per service". I would rather have the control over how many services I want to define which follow the same interface.

The second option you have, if you would rather not mess with the central registry in order to set up your tests, would be to redefine them inside your test class like this:

(a little more like the approach you currently use in your test, Jason)

From this point forward in your script, you know that whenever you retrieve the named service/component "order", it will be a mock one. I would even argue that this method allows you more flexibility during testing in that not every single class that you are testing needs to be extracted into a mock, you can inject the mocks at any point in the dependency chain, where it matters. I don't need a MockOrder class if all that is different about it is the database driver that I pass to it in order to run my tests.

My example is probably flawed in a dozen different ways, since I am no unit testing expert (I am falling way behind the majority on these forums) but it shows what I think would be a straightforward approach to modifying the dependency registry in order to carry out your tests.

Unfortunately, as Douglas explained, the "$this" scope is not available from within the function, although theres the "$di" parameter in case you want to make a traditional-style method call. Either way you are bound to either the name of the class or the name of the parameter, so it's kinda six on the one hand or a half a dozen on the other.

Would it be worth it to switch to eval() to get a $this and thus avoid the binding altogether?

You do Lazy Instansiate but not Lazy Load of classes. Probably could be handled elsewhere, but you might add the optional ablity to load the classes used. This give it some Handle qualities but you don't have to use it if you don't want to.

But... I don't really like having all that code in quotes. In Ruby, great. In PHP, it feels half baked. In Ruby you have the auto-return, you don't need "return $gateway;" and "$gateway =" is optional.

So, I'd say keep it simple by only doing constructor injection, then have this:

At the risk of adding even more DI code to the mix... I've just put together a preview release of my own home grown DI. It's vary rudimentary right now, but the current d51MutableInterfaceContainer is completely automatic. You call register('KnownClass') and it looks up the interfaces it implements.

Like I said, this is all very rudimentary. I need to create an interface container that doesn't rely on Reflection so the class does not have to be loaded in order to work. I will probably handle that by using containers that load config files. With that (those?) container(s) in place, it'll be easier to backport to PHP 4. ObjectFactory would need to change its instantiation so it automatically knows what/how to load itself instead of figuring it out when loadObject() is called.

Thoughts and comments are always welcome.

As a side note - regardless of the actual proveable usefullness of DI in the real world... this was a heck of a lot of fun to code