Dependency injection with Xml and Yaml in the Ding containerTweet
Introduction to Dependency Injection for your PHP Code with XML and YAML
In "Use Annotations in your PHP Code to achieve Dependency Injection with the Ding Container" I've discussed the dependency injection features when using annotations. This time, we'll see how to use the xml and yaml drivers to do the same (setter and constructor injection). If you don't know how to configure the xml and yaml drivers, please start by reading "Ding container: Using the Xml, Yaml, and Annotations drivers".
In the ding manual you can find extensive examples (almost all with xml and annotations). You are encouraged to take a look at it. This article will reproduce some of the examples there, extending the concepts a little bit, and giving some missing-from-the-manual YAML examples.
Also, the manual explains other stuff not mentioned here, like bean aliasing and inheritance, hooking in the bean lifecycle, aspect oriented programming (explained in "Aspect Oriented Programming in PHP with Ding"), factory beans and factory classes, etc.
Setter Injection for your PHP Application
Setter injection works given 2 conditions:
- You declare "properties" in your bean definitions.
- You include the needed setter methods in your classes.
Quick example: You have a repository class, and you want to set a value when you create an instance of it. Let's say you want to set the DB driver for a given repository, you could do something like:
In this case, you would define a "driver" property. And ding will automatically look for a "setDriver" method and use it to inject the configured values. The convention is that the property name is upercamel cased first, and then prepended with the word set. The new string is the name of the method to be called to perform the setter injection. That's it. Let's now see how to actually do this :)
Injecting scalar variables
The general syntax for setter injection with xml is the following:
Equivalent with YAML:
You can also insert some special values, like "true", "false", or "null":
Injecting php code
Of course, doing this is not recommended. But if you really need to, you can execute code and have the result injected as a property in your beans:
Injecting user properties
You can also inject property values. In this case, we are injecting a property registered in the container or the properties holder. In this case, the container will inject the value of the property "user.name":
Injecting references to other beans (collaborators)
The usual case is the need to have a bean collaborating with another one. This translates into a bean having a dependency on another bean (the collaborator). To achieve this:
You can also define a collaborator in the actual property where it will be injected, instead of defining the collaborator globally. This is useful to cleanup your xml/yaml files. These are called inner beans, which also, can be anonymous (i.e: without a given name):
Being a bean definition themselves, you can have setter and constructor injection as well, and every other feature available when defining beans.
You can also inject arrays with values, specifying an optional key for each entry. In the following example, an associative array is injected, with several different values. Note how you can combine the syntax we saw above (remember, the array keys are completely optional):
Constructor Injection for your PHP Classes
Constructor injection is pretty much equal to setter injection. The syntax for declaring constructor arguments is a little different, but you can use the same syntax to specify the values for the constructors. The constructor arguments are evaluated IN ORDER. But you can optionally specify the "name" of the argument
Specifying constructor argument names:
In YAML you would do:
Constructors can be injected with arrays, user properties, inner beans, etc. All what we saw for setters (properties) also apply to constructors, so I wont go over it. Just try the same syntax as with setter injection :)
Method Injection: Use custom methods of your PHP Objects to inject dependencies
Method injection allows you to override a method in a given bean. In this case, the method "createDependency" in the bean "myBeanName" will be overriden (by the container) with an implementation that returns the bean "dependencyName".
This is a nice feature, very useful in certain ocasions. See "Method Injection".
Start enhancing your PHP Code: Dependency Injection everywhere
So you've seen an overview of how to make ding completely assemble your application components without using annotations. But, XML and YAML can get quite verbose, that's why I personally preffer to use annotations. But, xml and yaml can be really handy sometimes, and actually complements the annotations. Besides that, they provide a non-invasive way of configuring our dependencies, so that's cool to have, too.