DI and property injection

12 years ago by David Grudl  

Dependency Injection is the apparent passing of dependencies, i.e., each class openly claiming its dependencies instead of surreptitiously acquiring them from somewhere. What if dependencies were passed directly to variables? I'll discuss the pitfalls and benefits of property injection.

Property injection has one significant advantage: brevity. Compare:

class Foobar
{
	/** @var HttpRequest */
	private $httpRequest;

	/** @var Router */
	private $router;

	function __construct(HttpRequest $httpRequest, Router $router)
	{
		$this->httpRequest = $httpRequest;
		$this->router = $router;
	}

}

vs.

class Foobar
{
	/** @var HttpRequest @inject */
	public $httpRequest;

	/** @var Router @inject */
	public $router;

}

We have to define variables anyway. Usually, we include an annotation @var and the corresponding data type. It is tempting to save yourself the trouble and add a simple @inject instead of writing routine constructor or method code inject(). In addition to minimal code overhead, property injection neatly solves the problem of dependency passing and inheritance.

Using annotation is another convention for passing dependencies. I emphasize the word other because whether we enumerate dependencies as method arguments or by annotating, it is an equivalent activity. It's not a container dependency, it's just a convention; after all, containers haven't been mentioned yet, and the examples make sense.

In the article on passing dependencies, I avoided using variables in a wide arc because they have serious shortcomings:

  • public variables do not provide type checking
  • public variables do not provide immutability
  • private variables cannot be filled with any language construct
  • private variables are not part of the public API – therefore they are not a dependency declaration!
  • the disadvantages of both apply to protected variables

For properly property injection, we would need a read-only public variable with type checking. If PHP could do this, there would be nothing stopping us from using them.

(Update: PHP 8.1 already does this)