Fork me on GitHub
2017-11-28

Doctrine Annotations in the TYPO3 CMS core

Important changes when using field injection with Extbase

For TYPO3 CMS v9, the doctrine/annotations pakage is now used and this means the developer can now use Doctrine Annotations. In TYPO3 Extbase, the @inject tag on a property can be used to inject a dependency on a field. For TYPO3 CMS v9, one needs to use TYPO3\CMS\Extbase\Annotation\Inject rather than the known @inject tag.

A short, but important note on the visibility of the target field:
While previously protected or even private field visibility modifiers were used, the core team now recommends using a public field. This reduces the runtime overhead of the injection itself, since the field doesn't have to be force-opened through reflection.

Previous usage:

<?php

class FooController extends ActionController
{
  /**
   * @var \Vendor\Package\Domain\Repository\FooRepository
   * @inject
   */
  public $fooRepository
}

Easily migrated to TYPO3 CMS v9+ with backwards compatibility:

<?php

use TYPO3\CMS\Extbase\Annotation\Inject as inject;

class FooController extends ActionController
{
  /**
   * @var \Vendor\Package\Domain\Repository\FooRepository
   * @inject
   */
  public $fooRepository
}

The change is forward-compatible so you can use it today, as long as your IDE doesn't optimize the unused import away, but that's another story.

Idiomatic TYPO3 v9 Doctrine Annotation usage:

<?php

use TYPO3\CMS\Extbase\Annotation as Extbase;

class FooController extends ActionController
{
  /**
   * @var \Vendor\Package\Domain\Repository\FooRepository
   * @Extbase\Inject
   */
  public $fooRepository
}

The example above aliases all Extbase Annotations and binds them to the Extbase alias. This is actually how the Symfony community uses Annotations, since this allows Annotations living in any namespace and still being very clear about where the annotation originates.

You need to import the annotation to stay compatible on the long run. In TYPO3 v9 and up, a user deprecation will be triggered if you use the old @inject tag. Luckily it's fairly simple to migrate.

There are a bunch of other phpDoc tags in the TYPO3 core which are subsequently converted to Doctrine Annotations thx to Alexander Schnitzler.

I'm also currently working on IDE support in conjunction with Daniel Espendillers Annotation support plugin for IntelliJ based IDEs.

Bonus question:

But why do we need annotations?

Glad you ask! In compiled languages like Java or C#, annotations are a way to tell the compiler or the tooling what should be done to an expression, like statically weaving null checks into the byte-code, generating boring code like getters and setters or even generating DAOs from interfaces (like Hibernate does). In PHP, annotations are mostly a way to annotate a local field, method or class with meta information. In a sense it can be used to move configuration to the place where it's needed. - In the case of the @inject anotation, it's pretty obvious that the property will have something injected at runtime. The usage of annotations for configuration is a reason for huge debates, but I won't go into that.

Post History:

  • 29.11.2017: Amendments considering the field visibility

No Comments