DI Container & @inject (& property injection)

8 years ago

juzna.cz
Member | 249
+
0
-

New DI Container looks great, but I still miss some features which have been available in Java world for some time already, e.g. in Spring framework or EJB. The most obvious for me is @Inject annotation, which makes it even easier to define services.

In Java, I've got two ways, which translated into PHP would look like:
1/ setter injection – cleaner, longer

class X {
  protected $a;

  /** @inject */
  public function setA(\Ns1\A $a) { $this->a = $a; }
}

2/ property injection – shorter, not that clean

class X {
  /**
   * @var \Ns1\A
   * @inject
   */
  protected $a;
}

Container looks for methods/properties with @inject annotation and automatically injects them.
I don't need to write too much code, and in case of setter injection I don't need to specify setA() in config file.

Wouldn't it be nice to have such support as well?

8 years ago

HosipLan
Moderator | 4693
+
0
-

You can implement this in your CompilerExtension::beforeCompile()

8 years ago

David Grudl
Nette Core | 6886
+
0
-

I believe that this goes against the spirit od DI. No class except the DI container should not know about DI.

8 years ago

Patrik Votoček
Member | 2249
+
0
-

David Grudl wrote:

I believe that this goes against the spirit od DI. No class except the DI container should not know about DI.

I believe too… :-)

8 years ago

juzna.cz
Member | 249
+
0
-

Thanks for your comments.

David Grudl wrote:

I believe that this goes against the spirit od DI. No class except the DI container should not know about DI.

Somehow you're right, but I still consider it an appropriate way. When defining a service/class, you specify in constructor what it needs. Setter with @inject can be additional info from the class saying “and in addition to what I said in constructor, I also need this (these)”.

It says nothing explicitly about container, the class just says what it wants. Container just understands it and behaves appropriately.

Property injection is just a convenient way, so that one doesn't have to write a setter.

Magic?

The magic ™ starts with private/protected methods/properties, as they are not accessible normally and thus cannot be injected by normal user code. This surely goes against the spirit of DI (but just makes life easier once you get used to container so much that you forget it).

Outcome

I'll try to implement it and provide some examples, so we'll see how it would work in real life.

8 years ago

HosipLan
Moderator | 4693
+
0
-

It's pretty obviouse how it works, but as it was said, this doesn't belong to DI. Because you're moving the configuration from config/extensions to code. That is not OK. It may be handy, but it's not OK.

As I've said, you can implement this in CompilerExtension::beforeCompile() and provide it as an addon to Nette, if you wish :)

8 years ago

pekelnik
Member | 468
+
0
-

I agree with juzna that the @inject annotations are basically the same information as typehint in the constructor.

I agree with hosiplan that we are moving configuration to code.

Is it bad?

I thing not really.

We are already using annotations for many “configuration” purposes – so why not for mark injected dependecies.

8 years ago

HosipLan
Moderator | 4693
+
0
-

Why not make it as an addon for the beginning? ;)

8 years ago

David Grudl
Nette Core | 6886
+
0
-

What is the difference between required parameter in constructor and setter with @inject annotation?