Zum Hauptinhalt springen

TYPO3 Context API

| phptypo3entwicklung

Allgemeines

Mit Version 9 hält eine neue API Einzug in den TYPO3 Kosmos - die Context API. Worum es genau bei der Context API geht, möchte ich in diesem Artikel einmal näher beleuchten.

Bis Version 9 waren verschiedene Kotextbezogene Informationen, sowas wie:

  • Ist der User angemeldet?
  • Welche Sprache wird gerade verwendet?
  • In welchem Workspace befinde ich mich gerade?

verteilt über verschiedene Objekte: In den globalen Variablen: TSFE und BE_USER.

Dieser Defragmentierung geht man jetzt entgegen: Man vereint all die entsprechenden Aspekte unter der Context API und ermöglich uns - den Entwicklern - sogar unsere eigenen Aspekte hinzuzufügen. Folgende Aspekte bringt TYPO3 schon mit:

Klasse

Registrierter Name

\TYPO3\CMS\Core\Context\VisibilityAspectvisibility
\TYPO3\CMS\Core\Context\DateTimeAspectdate
\TYPO3\CMS\Core\Context\UserAspect

frontend.user oder backend.user

\TYPO3\CMS\Core\Context\WorkspaceAspect

workspace

\TYPO3\CMS\Core\Context\LanguageAspect

language

Kleiner Hinweis: Im Core einfach nur nach Aspect suchen bringt nicht den gewünschten Effekt in diesem Kontext, die entsprechende Klasse muss das Interface AspectInterface implementieren.

Benutzung

Die Nutzung ist einfach: Der Context ist ein Singleton und kann so in der eigenen Extension einfach per GeneralUtility::makeInstance

/** @var \TYPO3\CMS\Core\Context\Context $context */
$context = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Context\Context::class, null);

// Checking if a frontend user is admin
$isAdminUser = $context->getPropertyFromAspect('frontend.user', 'isAdmin');

 

Eigene Aspekte

Um einen eigenen Aspect zu definieren und registrieren fahren wir ähnlich fort:

class CustomAspect implements \TYPO3\CMS\Core\Context\AspectInterface {
    /**
     * Get a property from an aspect
     *
     * @param string $name
     * @return mixed
     * @throws AspectPropertyNotFoundException
     */
    public function get(string $name) {
        switch ($name) {
            case 'hello':
                return $this->getHello();
            default:
                throw new AspectPropertyNotFoundException();
        }
    }

    private function getHello()
    {
        return 'Hello';
    }
}

/** @var CustomAspect $customAspect */
$customAspect = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(CustomAspect::class, null);

/** @var \TYPO3\CMS\Core\Context\Context $context */
$context = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Context\Context::class, null);
$context->setAspect('guengoeren.custom', $customAspect);

Je nach Anforderung sollte das in einer entsprechenden Middleware passieren, so das der Aspekt über die ganze Laufzeit des Requests zur Verfügung steht. Wie man Middleware einsetzt habe ich hier beschrieben.

Eins muss man jedoch bei der Verwendung von eigenen Aspekten beachten: Das registrieren von eigenen Aspekten, die nur einen lesenden Charakter haben kann das globale Objekt genutzt werden. Sollte jedoch der Aspekt Datenbank Abfragen machen, die die Datengrundlage ändern, sollte man sich einen eigenen Context erstellen.

/** @var \TYPO3\CMS\Core\Context\Context $context */
$context = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Context\Context::class, null);
$alteringContext = clone $context;
$alteringContext->setAspect('alteringStateAspect', AlteringStateAspect::class);

// customService updates user data
$customService = GeneralUtility::makeInstance(CustomService::class, $alteringContext);

 

Fazit

Ich finde die Anpassungen in diesem Bereich gut. Sie bündelt verschiedene Concerns an einer Stelle, unter einer API. Das trägt zu der Codequalität im TYPO3 Core bei und macht die gesamte API zugänglicher. 

Zurück
Code Snippet shows a custom aspect