Aufbau einer Contao Erweiterung
In diesem Kapitel zeige ich, wie ich meine Erweiterungen aufbaue. Dies ist das Ergebnis der letzten Jahre und stellt
eine Art best practice dar, mit der ich am wenigsten Probleme habe. Es gibt gerade unter Contao 4 und Symfony viele
mögliche Wege. Einige Entwickler haben z. B. einen src
-Ordner in ihrer Erweiterung, auf den ich verzichte, da er aus
meiner Sicht keinen Vorteil bringt.
Es ist aber ganz klar, das dies hier nicht der Königsweg, oder das einzig richtige Vorgehen ist. Es ist nur ein Beispiel für einen funktionierenden Weg.
Namen
In Contao heißen die zusätzlichen Programmpakete in der Regel Erweiterung oder Extension, in Symfony werden sie oft als Bundles bezeichnet. Da in Contao 4 eine Erweiterung ein Bundle sein kann, werde ich die Bezeichnungen gleichwertig benutzen. Mir ist bewusst, dass dies historisch und technisch nicht ganz korrekt ist, muss den Einsteiger aber nicht wirklich interessieren.
Manche nennen sie auch Modul. Dies versuche ich zuvermeiden, da es in Contao Frontend- und Backendmodule gibt. Dies führt häufig zu Verwechselungen.
Kommandozeile oder Manager
Viele Operationen (wie das Leeren des Caches oder die Installation von Paketen) sind per Kommandozeile und über den Contao Manager möglich. Aus meiner Sicht kommt man beim Entwickeln nicht an der Kommandozeile vorbei, ich werde in meinen Texten deshalb diese Methode verwenden. Da der Manager relativ selbst erklärend ist, sollte die Umsetzung der einzelnen Schritte dort auch für Einsteiger ohne Erklärung möglich sein.
Überblick
app
├── config
│ └── parameters.yml
├── ContaoManagerPlugin.php
src
└── Ctocb
└── Example
├── Classes
│ ├── Contao
│ │ └── Manager
│ │ └── Plugin.php
│ ├── Events
│ │ └── OnDoSomethingEvent.php
│ ├── Listener
│ │ └── OnDoSomethingListener.php
│ └── Services
│ └── Helper
│ └── TestToken.php
├── Resources
│ ├── config
│ │ ├── listener.yml
│ │ └── services.yml
│ └── contao
│ ├── config
│ │ └── config.php
│ ├── dca
│ │ └── tl_test.php
│ ├── languages
│ │ └── de
│ │ └── tl_test.php
│ └── templates
│ └── ce_test.html5
├── .editorconfig
├── .gitignore
├── CtocbExampleBundle.php
├── README.md
└── composer.json
composer.json
Ich werde auf die wichtigsten Dateien nun genauer eingehen. Die Standarddateien von Contao (im Ordner
Resources/contao
) sollten hinreichend bekannt sein und werden in den Abschnitten zu den jeweiligen Themen erläutert.
Die restlichen Dateien der Contao-Installation wurden zur besseren Übersicht ausgeblendet.
Speicherort der Erweiterung
Wenn ich eine Erweiterung entwickle, liegt diese unter src/Ctocb/PROJEKT/
. PROJEKT
wird durch den Namen der
Erweiterung ersetzt. Hierauf zeigt dann auch der psr-4-Autoload-Eintrag in der composer.json
(s. nächster Abschnitt).
Im weiteren Verlauf werde ich das Projekt Example
nennen. Wo immer dies steht, muss es durch den Namen des
jeweiligen Projekts ersetzt werden!
Das Ctocb
ist mein Vendor-Namespace. Ihr müsst dies bitte durch Euren eigenen
Namespacce ersetzen. Dies kann ein Bezeichner für Eure Firma oder Euren Namen sind. Bitte NICHT Ctocb
verwenden!
Danke! (Wo auch immer Ctocb
in einem Namen oder Namespace steht, dies bitte durch Euren eingnen Namespace oder
Pfad ersetzten.)
composer.json
Es gibt die Datei composer.json
zwei Mal. Die erste ist die von Contao mitgebrachte. Sie konfiguriert die
Entwicklungsumgebung. Die zweite ist in unserer Erweiterung und konfiguriert die Abhängigkeiten und das Autoloading
unserer Erweiterung, nach der Installation in beim Benutzer.
composer.json der Entwicklungsumgebung
Damit das Manager Plugin (und durch dies auch unser Bundle) in der Entwicklungsumgebung gefunden wird, muss in den
Abschnitt autoload
der Datei composer.json
im Wurzelverzeichnis von Contao folgendes eingetragen werden:
"autoload": {
"classmap": [
"app/ContaoManager/Plugin.php"
],
"psr-4": {
"Ctocb\\": "src/Ctocb/"
}
}
Der Eintrag classmap
sorgt dafür, dass unser Plugin gefunden wird. Mit psr-4
konfigurieren wir den Autoload für die
Klassen unseres Bundles. In diesem Fall liegen die Dateien im Ordner src/Ctocb/
und der Teil des Namespaces Ctocb\\
wird im Pfad dann durch src/Ctocb/
ersetzt. Alles was folgt, wird auf die Unterordner gemappt. Hat eine Datei also den
Namespace Ctocb\Example\Classes\Contao\Manager
und den Namen Plugin
liegt sie unter
/src/Ctocb/Example/Classes/Contao/Manager/Plugin.php
.
Auch hier ist das Ctocb
ist mein Vendor-Namespace. Ihr müsst dies bitte durch Euren
eigenen Namespacce ersetzen.
composer.json der Erweiterung
In der composer.json
der Erweiterung muss als type
entweder contao-provider
für die Installation als Artefakt
über den Manager, oder contao-bundle
bei einer Installation über ein VCS.
Im Abschnitt require
stehen erst einmal PHP und Contao. Später werden ggf. weitere Pakete eingefügt, wenn wir weitere
Abhängigkeiten benötigen. Wichtig ist, dass diese zwar über composer in die Entwicklungsumgebung installiert werden
können, aber immer nur in der globalen composer.json
der Installation eingetragen werden.
In unserer Erweiterung müssen die Abhängigkeiten manuell gepflegt werden!
Neben dem PSR-4 Eintrag für das Autloading, wird hier auch unter extra
das ManagerPlugin bekannt gegeben.
{
"name": "Ctocb/Example",
"description": "Es handelt sich um eine Erweiterung für das Open Source CMS Contao",
"license": "proprietary",
"type": "contao-bundle",
"authors": [
{
"name": "Patrick Froch",
"email": "info@easySolutionsIT.de",
"homepage": "http://easySolutionsIT.de",
"role": "Developer"
}
],
"support": {
"email": "info@easySolutionsIT.de"
},
"require": {
"php": "^8.1",
"contao/manager-bundle": "^4.13"
},
"require-dev": {
"contao/test-case": "^4.13",
"phpunit/phpunit": "^9.5"
},
"autoload": {
"psr-4": {
"Ctocb\\Example\\": ""
}
},
"extra": {
"contao-manager-plugin": "Ctocb\\Example\\Classes\\Contao\\Manager\\Plugin"
}
}
Auch hier bitte alle Vorkommen von Ctocb
durch Euren eigenen Namespacce ersetzen.
Ab jetzt werde ich es nicht mehr erwähnen, ich hoffe das Prinzip ist klar. ;)
Zwei Plugins für ein Bundle
Etwas unschön ist, dass wir für unsere Bundles auch zwei Plugins benötigen. Eins für die Entwicklungsumgebung und eins, das mit der Erweiterung ausgeliefert wird. Leider ist dies zurzeit nicht anders möglich.
Erweiterung
Das Manger Plugin der Erweiterung liegt bei mir in /src/Ctocb/Example/Classes/Contao/Manager
und trägt den Namen
Plugin.php
. Die Details des Manager Plugins werden im nächsten Kapitel besprochen, sodass ich hier nur ein Beispiel
zeige:
<?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;
class Plugin implements BundlePluginInterface, ConfigPluginInterface
{
public function getBundles(ParserInterface $parser)
{
return [BundleConfig::create(CtocbExampleBundle::class)->setLoadAfter([ContaoCoreBundle::class])];
}
public function registerContainerConfiguration(ParserInterface $parser)
{
$path = '@CtocbExampleBundle/Resources/config';
$loader->load("$path/services.yml");
}
}
Entwicklungsumgebung
Im Contao Handbuch steht, dass das Plugin unter
\App\ContaoManager\Plugin.php
liegen soll. Trotz intensiver Versuche funktioniert dies bei mir nicht. Die Klasse
wird bei mir nur geladen, wenn Sie ContaoManagerPlugin
heißt. Vielleicht habe ich es aber auch falsch verstanden.
Ich gehe erst einmal weiter den Weg, dass ich das Manager Plugin unter app/ContaoManagerPlugin.php
speichere.
Diese Klasse enthält keine Logik, sie erbt einfach vom Manager Plugin unserer Erweiterung.
<?php declare(strict_types=1);
use Ctocb\Example\Classes\Contao\Manager\Plugin;
class ContaoManagerPlugin extends Plugin {}
Bundle
Die Bundle-Klasse muss im Wurzelverzeichnis der Erweiterung liegen (/src/Ctocb/Example/CtocbExampleBundle.php
) und
enthält ebenfalls meist keine Logigk.
<?php declare(strict_types=1);
namespace Ctocb\Example;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class CtocbExampleBundle extends Bundle {}
Konfiguration für Contao
Die Konfigurationen sind seit Contao 3 eigentlich unverändert geblieben und liegen im Ordner
/src/Ctocb/Example/Resources/contao
. Wie gesagt, werde ich diese Dateien in den jeweiligen Kapiteln erläutern.
Symfony Dateien
Auf die Dateien, die für Symfony eine Rolle spielen (wie Events, Listener, Services oder die YML-Dateien), werde ich auch in den jeweiligen Kapiteln eingehen. Sie wurden im Listing weiter oben nur gezeigt, um einen groben Überblick über die Systematik der Aufteilung zu geben.