[2241 Aufrufe]

4.1 Grundlagen der Callbacks

In diesem Text möchte ich auf die Grundlagen der Callbacks in Contao eingehen. Die Calbacks werden bei der Verarbeitung des DCA aufgerufen, wenn bestimmten Vorkommnissen eintreten. Es gibt z. B. einen Callback, der beim Laden eines Werts für ein Feld im Backend aufgerufen wird. Ein anderer wird beim Speichern des Werts aufgerufen. Eine Liste der Callbacks ist im Handbuch zu finden.

Es gibt verschiedene Arten von Callbacks. Die globalen Callbacks werden bei Aktionen, die sich auf die Tabelle beziehen aufgerufen. Die Callbacks für die Auflistung sind beim Anzeigen der Listen der Datensätze im Backend wichtig. Mit Callbacks für Aktionen steuert man das Verhalten bei Aktionen der einzelnen Datensätze (wie Kopieren, Löschen, ...). Mit den Callbacks für Felder ändern man das Verhalten der Felder.

Ab Contao 4.9 könnte man die Callbacks direkt in der Klasse per Service Annotation registrieren und ab PHP 8 per Attribut. Dies hat aus meiner Sicht aber den Nachteil, dass man in allen Klassen nach der Registierung suchen muss. Ich habe die Konfiguration lieber in einer Datei, sodass ich alles auf einen Blick sehe. Ich werde hier diesen Weg zeigen, da er mit allen Versionen funktioniert, meinen Vorlieben entspricht und (soweit ich weiß) keine Nachteile hat. Die Vorgehensweise mit Annotaions wird in den Beispielen im Handbuch beschreiben.

Bitte auch in diesem Artikel wieder den Vendor-Namespace (und/oder entsprechenden Ordner) durch Euren eignen ersetzen und nicht Ctocb verwenden! Danke!

Allgemeines Vorgehen

Die Callbacks werden in der Datei /src/Ctocb/Example/Resources/config/services.yml registriert.

services:
    Ctocb\Example\Classes\Contao\Callbacks\TlTest:
        public: true
        tags:
            - { name: contao.callback, target: config.onload, table: tl_test, method: myCallback, priority: 1024 }

In Zeile 2 steht der Name der Klasse. In Zeile 3 wird der Service öffentlich gemacht. Dies ist nötig, wenn man ihn in Contao verwenden will (wie hier als Callback, oder z. B. über \System::getContainer()->get('...')). In Zeile 4 stehen die Tags, die den Service zum Callback machen. Der Eintrag name: contao.callback tut genau dies und target: config.onload legt fest auf welches Ereignis reagiert werden soll. table: tl_test sagt für welche Tabelle der Callback aufgerufen werden soll und method: myOnloadCallback welche Methode in der Klasse zuständig ist. Zusätzlich kann man noch eine Priorität angeben. Diese legt fest, in welcher Reihenfolge die Callbacks aufgerufen werden, wenn es mehrere gibt. Ich verwende standardmäßig 1024. So ist es möglich sowohl davor als auch dahinter noch weitere Callbacks zu registrieren, falls dies nötig sein sollte.

Gerade die Priorität ist ein erheblicher Vorteil, gegebenüber dem Registrieren der Callbacks über ein globales Array.

Damit unsere Services geladen werden, müssen wir das Manager Plugin etwas erweitern:

<?php declare(strict_types=1);

namespace Ctocb\Example\Classes\Contao\Manager;

use Contao\CoreBundle\ContaoCoreBundle;
use Contao\ManagerPlugin\Bundle\BundlePluginInterface;
use Contao\ManagerPlugin\Bundle\Config\BundleConfig;
use Contao\ManagerPlugin\Bundle\Parser\ParserInterface;
use Contao\ManagerPlugin\Config\ConfigPluginInterface;
use Ctocb\Example\CtocbExampleBundle;
use Symfony\Component\Config\Loader\LoaderInterface;

class Plugin implements BundlePluginInterface, ConfigPluginInterface
{

    public function getBundles(ParserInterface $parser)
    {
        return [BundleConfig::create(CtocbExampleBundle::class)->setLoadAfter([ContaoCoreBundle::class])];
    }

    public function registerContainerConfiguration(LoaderInterface $loader, array $config)
    {
        $path = '@CtocbExampleBundle/Resources/config/';
        $loader->load("$path/services.yml");
    }
}

Die Methode registerContainerConfiguration ist neu und lädt in Zeile 23 und 24 unsere Servicedefinition. Wichtig ist, dass das Plugin das ConfigPluginInterface implementiert. Wird dies vergessen, passiert nichts.

Die Klasse für die Bearbeitung des Callbacks wird unter /src/Ctocb/Example/Classes/Contao/Callbacks/TlTest.php gespeichert. Wenn der Namespace stimmt, kann natürlich jede beliebige Datei verwendet werden. Sie muss natürlich eine Methode mit dem Namen haben, den wir mit method angegeben haben.

<?php declare(strict_types=1);

namespace Ctocb\Example\Classes\Contao\Callbacks;

class TlTest
{
    public function myCallback($dc = null): void
    {
        // do something ...
    }
}

In den weiteren Artikeln werden wir auf die einzelnen Callbacks eingehen. Wir fangen im nächsten Text mit den globalen Callbacks an.

(An dieser Stellen noch einmal die dringende Bitte, den Vendor-Namespace (und/oder entsprechenden Ordner) durch Euren eignen zu ersetzen und nicht Ctocb zu verwenden! Vielen Dank!)