Logo Time4Digital Logo Time4Digital
  • Webagentur
  • Dienstleistungen
    Alle Dienstleistungen im Überblick
    Webentwicklung und Softwareentwicklung
    Support für Ihre Website & Webanwendung
    Innovative & nachhaltige Webseiten Agentur
    Onlinemarketing & Suchmaschinen-Optimierung
    Content Management Systeme
    E-Commerce-Lösungen
    Lokale SEO Agentur
  • Portfolio
  • Webseiten
  • Team
  • Insights
  • Termin
    buchen
  • Gratis
    SEO Check
  • English
  • Deutsch
  • French

Hello World Contao Plugin erstellen: Front- & Backendentwicklung

Geschrieben am 16.04.2024 08:15 von rd

Inhaltsverzeichnis

Navigation überspringen
  • Die Dateistruktur des Contao Plugins
  • Contao Plugin: Basis Aufbau
    • Aufbau vom Composer
    • Aufbau der Bundle Klasse
    • Aufbau der Plugin Klasse von Contao
    • Aufbau der Dependency Klasse
    • Die Config und Services Datei
  • Contao "Hello World" Frontend-Modul Aufbau
    • Aufbau der Frontend-Modul Klasse
    • Frontend-Modul ins Backend bringen
    • Template-Datei für das Frontend-Modul
    • CSS und JS ins Contao-Modul einbinden.
  • Contao Backend-Modul: Aufbau und Datenbankeinbindung
    • Datenbanktabellenerstellung mit DCA
    • Übersetzungen der Felder
    • Backend-Modul ins Contao-Backend bringen
    • Backend-Daten ins Frontend anzeigen
 
Plugin Darstellung im Frontend

Der Anfang kann oft eine Herausforderung darstellen. Selbst für erfahrene Entwickler wie uns ist das Eintauchen in neue Technologien häufig mit Schwierigkeiten verbunden. Die Prinzipien, die hinter der Entwicklung eines Contao-Plugins stehen, zu begreifen und diese zu nutzen, um die eigene Contao-Website mit kreativen Plugins zu bereichern, benötigt Zeit. Obwohl die Dokumentation einen soliden Überblick bietet, stößt man bei spezifischeren Fragen häufig auf Limitierungen.

Aus diesem Grund haben wir uns entschlossen, einen Leitfaden zu erstellen, der erklärt, wie man ein einfaches „Hello World“ Contao Plugin entwickelt. Dieser Artikel ist leicht verständlich und liefert euch das notwendige Hintergrundwissen, um eigene Contao Plugins  zu erstellen – sowohl für das Frontend als auch für die Backendentwicklung.

In diesem Artikel lernt ihr:

- Wie man die Grundlagen eines Plugins anlegt
- Wie man einen „Hello World“-Text im Frontend darstellt
- Welche Struktur die Daten haben sollte
- Wie man eine Verbindung zur Datenbank herstellt

Am Ende sollt ihr ein „Hello World“ Contao Plugin programmiert haben, das zusätzlich Nachrichten anzeigt, die im Backend definiert wurden.

Solltet ihr Unterstützung bei der Entwicklung oder beim Support eurer Websiten benötigen, schaut euch unsere CMS-Lösungen oder unseren Support für Webseiten und Webanwendungen an. Wir stehen euch gerne zur Verfügung!

Das Code für das Plugin ist in Github unter diesem Link verfügbar. Ihr könnt diesen gerne zu Testzwecken verwenden.

Die Dateistruktur des Contao Plugins

Die Contao Plugin Dateistruktur muss unbedingt eingehalten werden, damit der Contao Manager das Plugin auch als solches erkennt und korrekt lädt.

Die Dateistruktur des Plugins dient als Orientierung für den Aufbau des Plugins

Contao Plugin: Basis Aufbau

Zunächst ist es erforderlich, das Contao Plugin so zu konfigurieren, dass es vom Contao Manager als Plugin erkannt und installiert werden kann. Dazu müssen die nachstehenden Klassen erstellt und entsprechend modifiziert werden:

Aufbau vom Composer

Contao nutzt den PHP Composer zur Verwaltung von Modulen, Erweiterungen und Plugins. Aus diesem Grund benötigt unser Contao Plugin ebenfalls eine Composer-Konfigurationsdatei, die sich im Hauptverzeichnis des Plugins befindet. Wenn du die Beispiel-JSON-Datei von Composer verwendest, stelle sicher, dass du alle mit # gekennzeichneten Werte entsprechend anpasst.



./composer.json

{
  "name": "time4digital/dylans-hello-world-bundle",               #Name vom Plugin
  "description": "Dylan's Hello World Plugin",                    #Beschreibung vom Plugin
  "license": "LGPL-3.0-or-later",
  "type": "contao-bundle",
  "version": "0.0.4",                                             #Version vom Plugin
  "authors": [
    {
      "name": "Ribeiro de Serra Dylan",
      "homepage": "https://www.time4digital.lu"                   #Authoren vom Plugin
    }
  ],
  "homepage": "https://contao.org",                               #OPTIONAL: Deine Webseite                    
  "support": {
    "issues": "https://github.com/ridy01-backup/contao-plugins/issues",   #OPTIONAL: Git Verlinkung.
    "source": "https://github.com/ridy01-backup/contao-plugins"
  },
  "require": {
    "php": "^8.1",
    "contao/core-bundle": "^4.13 || ^5.0"                                   #Deine Dependencies musst du hier setzen.
  },
  "require-dev": {
    "bamarni/composer-bin-plugin": "^1.5",
    "contao/manager-plugin": "^2.0",
    "phpunit/phpunit": "^9.5",
    "symfony/phpunit-bridge": "^6.1"
  },
  "conflict": {
    "contao/manager-plugin": "<2.0 || >=3.0"                                #Mögliche Konflikte kommen hier.
  },
  "autoload": {
    "psr-4": {
      "Time4digital\\DylansHelloWorldBundle\\": "src/"                      #Der Pfad welches Wired wird, Format: "VendorName\\BundleName\\": "PFAD"
    }
  },
  "autoload-dev": {
    "psr-4": {
      "Time4digital\\DylansHelloWorldBundle\\Tests\\": "tests/"             #Der Pfad für die Tests, Format: "VendorName\\BundleName\\Tests": "PFAD"
    }
  },
  "config": {
    "allow-plugins": {
      "bamarni/composer-bin-plugin": true,
      "contao-components/installer": true,
      "contao/manager-plugin": true
    }
  },
  "extra": {
    "bamarni-bin": {
      "bin-links": false,
      "target-directory": "tools"
    },
    "contao-manager-plugin": "Time4digital\\DylansHelloWorldBundle\\ContaoManager\\Plugin"    #Plugin Verlinkung, Format:"VendorName\\BundleName\\ContaoManager\\Plugin
  },
  "scripts": {
    "all": [
      "@unit-tests",
      "@ecs",
      "@phpstan"
    ],
    "ecs": "@php tools/ecs/vendor/bin/ecs check src tests --config ecs.php --fix --ansi",
    "phpstan": "@php tools/phpstan/vendor/bin/phpstan analyze --ansi",
    "unit-tests": "@php vendor/bin/phpunit --colors=always"
  }
}

Aufbau der Bundle Klasse

Die Bundle Klasse ist dafür da, deine Ressourcen zu bündeln. Diese Klasse selbst erfordert keine weiteren Spezifikationen; es reicht einfach aus, die Klasse vom Symfony Bundle zu erweitern.

./src/DylansHelloWorldBundle.php

<?php
namespace Time4digital\DylansHelloWorldBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class DylansHelloWorldBundle extends Bundle
{
    
}

Aufbau der Plugin Klasse von Contao

Die Plugin-Klasse dient dazu, das Bundle zu laden, damit der Contao Manager weiß, dass es sich um ein Contao Plugin handelt.

./src/ContaoManager/Plugin.php

<?php

declare(strict_types=1);

namespace Time4digital\DylansHelloWorldBundle\ContaoManager;

use Contao\ManagerPlugin\Bundle\BundlePluginInterface;
use Contao\ManagerPlugin\Bundle\Config\BundleConfig;
use Contao\ManagerPlugin\Bundle\Parser\ParserInterface;
use Contao\CoreBundle\ContaoCoreBundle;
use Time4digital\DylansHelloWorldBundle\DylansHelloWorldBundle;

class Plugin implements BundlePluginInterface
{
    /**
     * {@inheritdoc}
     */
    public function getBundles(ParserInterface $parser)
    {
        return [
            BundleConfig::create(DylansHelloWorldBundle::class)
                ->setLoadAfter([ContaoCoreBundle::class]),
        ];
    }
}

Aufbau der Dependency Klasse

Die Dependency-Klasse dient dazu, die Konfigurations- und Services-Dateien zu laden.

./src/DependencyInjection/DylansHelloWorldExtension.php

<?php
declare(strict_types=1);

namespace Time4digital\DylansHelloWorldBundle\DependencyInjection;

use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;

class DylansHelloWorldExtension extends Extension
{
    /**
     * {@inheritdoc}
     */
    public function load(array $mergedConfig, ContainerBuilder $container)
    {
        $loader = new YamlFileLoader(
            $container,
            new FileLocator(__DIR__.'/../Resources/config')
        );

        $loader->load('services.yml');
    }
}

Die Config und Services Datei

Die Config- und Services-Dateien dienen dazu, die Klassen, die man innerhalb des Bundles schreibt, zu verknüpfen, damit sie beim Installieren geladen und verwendet werden können.

./src/Resources/config/config.yml

imports:
    - { resource: services.yml }

./src/Resources/config/services.yml

services:
    _defaults:
        autowire: true
        autoconfigure: true

Und somit wäre die Basis des Plugins aufgebaut. Nun könnte man das Plugin zippen, über den Contao Manager hochladen und installieren.
Doch das allein reicht noch nicht aus, um 'Hello World' im Frontend anzuzeigen.

Contao "Hello World" Frontend-Modul Aufbau

In diesem Abschnitt erstellen wir ein Frontend-Modul, das im Frontend "Hello World" anzeigen soll.
Das Modul lädt außerdem zusätzlich eine CSS- und JS-Datei.

Aufbau der Frontend-Modul Klasse

Die Modul Klasse dient dazu, ein Modul im Backend zu erstellen, welches dann in einem Artikel oder Ähnlichem geladen werden kann.

./src/Module/DylanHelloWorldModule.php

<?php

namespace Time4digital\DylansHelloWorldBundle\Module;

use Contao\Module;

//Hier werden die CSS- und JS-Dateien gesetzt. Format: bundles/bundleName/dateiName.dateExtension
$GLOBALS['TL_CSS'][] = 'bundles/dylanshelloworld/styles.css';
$GLOBALS['TL_JAVASCRIPT'][] = 'bundles/dylanshelloworld/scripts.js';

class DylanHelloWorldModule extends Module
{
    // Hier wird der Name des Templates festgelegt.
    // Der Name muss mit dem Template übereinstimmen, das sich unter ./src/Resources/contao/templates befindet.
    protected $strTemplate = 'mod_helloWorld'; 

    protected function compile()
    {
        // Mit $this->Template->nameVariable erstellst du Variablen, die dann im Template verwendet werden können.
        $this->Template->message = 'Hello World!';
    }
}

Frontend-Modul ins Backend bringen

Die Config PHP Datei dient dazu, um Modulen ins Backend zu bringen.

./src/Resources/contao/config/config.php

<?php
use Time4digital\DylansHelloWorldBundle\Module\DylanHelloWorldModule;

// Frontend modules
// Unter "miscellaneous" sollte ein neuer Reiter namens "Hello World Plugin" erstellt werden, welches dann unser Frontend-Modul lädt.
$GLOBALS['FE_MOD']['miscellaneous']['Hello World Plugin'] = DylanHelloWorldModule::class;

Template-Datei für das Frontend-Modul

Die Template-Datei wird sozusagen als Container für das Modul verwendet. Dort bindest du die Daten ein, die du im Modul definierst, und baust dir somit eine HTML-Struktur auf.

./src/Resources/contao/templates/modules/mod_helloWorld.html5

<?php $this->extend('block_searchable'); ?>

<?php $this->block('content'); ?>

<!-- Hier verwenden wir den Wert der message-Variable -->
<div class="dylan-hello-world-container">
    <?= $this->message; ?>
</div>

<?php $this->endblock(); ?>

CSS und JS ins Contao-Modul einbinden.

Du kannst eigene CSS- und JS-Dateien in das Contao-Modul einbinden, wie im Modul oben definiert. Du musst dazu nur folgende Dateistruktur einhalten (der Name der Datei spielt dabei keine Rolle):

./src/Resources/public/scripts.js

./src/Resources/public/styles.css

... und voilà, schon kannst du im Backend unter Themes > Frontend Module ein neues Modul erstellen und wählst dann einfach als Modultyp das Hello World Contao Plugin aus!

Dann gehst du auf irgendeinen Artikel oder Ähnliches und wählst dort das erstellte Modul aus.

Demonstration der Erstellung eines Frontend-Moduls aus dem programmierten Frontend-Modul
Im Contao Backend den Frontend-Module in einem Artikel zuweisen

Puh, das war schon eine Menge Arbeit... doch das reicht noch nicht ganz aus! Zwar würde unser Frontend-Modul ausreichen, um im Frontend etwas Schönes anzuzeigen, das mit PHP-Funktionen ausgestattet wäre... doch was ist, wenn wir zusätzlich Daten aus der Datenbank laden und über das Contao-Backend verwalten möchten?

Im nächsten Abschnitt gehen wir genau auf diesem Punkt im Detail ein.

Contao Backend-Modul: Aufbau und Datenbankeinbindung

In diesem Abschnitt erstellen wir ein Backend-Modul, das Daten aus einer Tabelle namens tl_messages lädt und zusätzlich bearbeitet werden kann. Das Ganze sollte im Contao-Backend unter einem Menüpunkt sichtbar sein.
Außerdem erweitern wir das Frontend-Modul, damit es auch die Daten aus dem Backend liest.

Datenbanktabellenerstellung mit DCA

Mit der DCA-PHP-Datei kannst du Contao mitteilen, dass du eine neue Datenbanktabelle erstellen möchtest.
Damit konfigurierst du die Struktur der Tabelle und definierst, wie die Daten angezeigt werden sollen.

./src/Resources/contao/dca/tl_messages.php

<?php
use Contao\DC_Table;

// Der Name der Tabelle; die PHP-Datei sollte entsprechend benannt werden.
$GLOBALS['TL_DCA']['tl_messages'] = [

    // Hier wird festgelegt, was im Contao-Backend angezeigt werden soll:
    'palettes' => [
        'default' => '{messages_legend},message;'
    ],

    // Die SQL-Felder werden hier definiert:
    'fields' => [
        // Dieses Feld ist obligatorisch.
        'id' => [
            'sql' => "int(10) unsigned NOT NULL auto_increment",
        ],
        // Dieses Feld ist obligatorisch.
        'tstamp' => [
            'sql' => "int(10) unsigned NOT NULL default '0'",
            'label' => 'TS',
        ],
        'message' => [
            'inputType' => 'text',
            'eval' => ['tl_class' => 'w50', 'maxlength' => 255],
            'sql' => "varchar(255) NOT NULL default ''"
        ]
    ],
    
    // Hier werden die Keys und weitere Attribute festgelegt.
    'config' => [
        'dataContainer' => DC_Table::class,
        'sql' => [
            'keys' => [
                'id' => 'primary'
            ]
        ]
    ],

    // Hier wird auch definiert, wie das Ganze im Contao-Backend dargestellt wird.
    'list' => [
        'sorting' => [
            'mode' => 1,
        ],
        'operations' => [
            'edit',
            'delete',
        ],
        'label' => [
            'fields'  => ['id','message'],
            'showColumns' => true,
        ]
    ],
];

Übersetzungen der Felder

Mit der Übersetzungs-XLF-Datei kannst du die Labels und Beschreibungen der Felder für verschiedene Sprachen definieren.

./src/Resources/contao/languages/en/tl_messages.xlf

<?xml version="1.0" ?><xliff version="1.1">
<!-- Format: contao/languages/SPRACHE/TABELLE.php-->
  <file datatype="php" original="contao/languages/en/tl_messages.php" source-language="en">
    <body>
        <!-- Legendenbezeichnung im Contao-Backend-->
        <trans-unit id="tl_messages.messages_legend">
            <source>Messages</source>
        </trans-unit>
        <!-- Bezeichnung des Feldes "Nachricht"-->
        <trans-unit id="tl_messages.message.0">
            <source>Message</source>
        </trans-unit>
        <!-- Beschreibung des Feldes "Nachricht"-->
        <trans-unit id="tl_messages.message.1">
            <source>Your individual message.</source>
        </trans-unit>
    </body>
  </file>
</xliff>

Backend-Modul ins Contao-Backend bringen

Die Config-PHP-Datei muss nun wie beim Frontend-Modul angepasst werden.

./src/Resources/contao/config/config.php

<?php
use Time4digital\DylansHelloWorldBundle\Module\DylanHelloWorldModule;

// Frontend modules
// Unter "miscellaneous" sollte ein neuer Reiter namens "Hello World Plugin" erstellt werden, welches dann unser Frontend-Modul lädt.
$GLOBALS['FE_MOD']['miscellaneous']['Hello World Plugin'] = DylanHelloWorldModule::class;

// Backend modules
// Unter der Menükategorie "content" sollte nun ein neuer Menüeintrag namens "Messages" erscheinen, der die Tabelle tl_messages verwaltet.
$GLOBALS['BE_MOD']['content']['Messages'] = [
    'tables' => ['tl_messages']
];

Backend-Daten ins Frontend anzeigen

Dazu müssen das Template und das Frontend-Modul angepasst werden.

./src/Module/DylanHelloWorldModule.php

<?php

namespace Time4digital\DylansHelloWorldBundle\Module;

use Contao\Module;

//Hier werden die CSS- und JS-Dateien gesetzt. Format: bundles/bundleName/dateiName.dateExtension
$GLOBALS['TL_CSS'][] = 'bundles/dylanshelloworld/styles.css';
$GLOBALS['TL_JAVASCRIPT'][] = 'bundles/dylanshelloworld/scripts.js';

class DylanHelloWorldModule extends Module
{

    // Hier wird der Name des Templates festgelegt.
    // Der Name muss mit dem Template übereinstimmen, das sich unter ./src/Resources/contao/templates befindet.
    protected $strTemplate = 'mod_helloWorld'; 

    protected function compile()
    {
       
        // Mit $this->Template->nameVariable erstellst du Variablen, die dann im Template verwendet werden können.
        $this->Template->message = 'Hello World!';
        
        // Die Module Klasse gibt uns die Möglichkeit, Datenbankeinträge schnell über die Contao Database-Klasse zu laden.
        // Hier rufe ich die Daten über eine SQL-Abfrage ab. Diese Abfrage extrahiert Datenbankeinträge aus der Datenbank und speichert sie in einem Array.
        try {
            $objEntries = $this->Database->execute("SELECT * FROM tl_messages");
            $this->Template->entries = $objEntries->fetchAllAssoc();
        } catch (\Exception $e) {
        // Falls das nicht funktioniert, wird einfach ein leerer Array dem Template zugewiesen.
            $this->Template->entries = [];
        }
    }
}

./src/Resources/contao/templates/modules/mod_helloWorld.html5

<?php $this->extend('block_searchable'); ?>

<?php $this->block('content'); ?>

<!-- Hier verwenden wir den Wert der message-Variable -->
<div class="dylan-hello-world-container">
    <?= $this->message; ?>
</div>

<!-- Hier durchlaufen wir das entries-Array und entnehmen für jedes Element den Wert der Nachricht -->
<div class="dylans-hello-world-live-container">
    <ul>
        <?php foreach ($this->entries as $entry): ?>
        <li><?= $entry["message"]; ?></li>
        <?php endforeach; ?>
    </ul>
</div>

<?php $this->endblock(); ?>

Finally, we got it! Nach vielen Höhen und Tiefen haben wir den Gipfel erreicht. Zeit zur Freude! ;-)

Nach der Neuinstallation des Contao Plugins sollte nun ein neuer Menüpunkt namens "Messages" vorhanden sein, über den neue Nachrichten erstellt werden können. Anschließend sollte unser Frontend-Modul all diese Nachrichten anzeigen.

Im Contao-Backend befindet sich nun der Menüreiter 'Messages', der dazu dient, Nachrichten zu erstellen

Wir hoffen, dass ihr durch diesen Blog-Artikel mehr über die Contao-Plugin-Entwicklung gelernt habt.

Wichtig anzumerken ist, dass es mehrere Wege gibt, dieses Plugin umzusetzen, und dieser Artikel lediglich ein Beispiel darstellt. Es steht Ihnen komplett frei, wie Sie Ihr Hello World Plugin entwickeln, solange die Basis richtig ist und der Contao Manager es als Plugin erkennt und installiert.

Weitere Informationen findest du hier.

Außerdem kannst du das Plugin auch direkt über diesen Link herunterladen und natürlich auch weiterentwickeln.

Vielen Dank für das Lesen dieses Blog-Artikels! Ich hoffe du hattest spaß und konntest etwas lernen. Weiterhin viel Spaß beim Entwickeln!

Der Artikel kann Medium Aritkel in Englisch auch auf englisch gelesen werden.

  • Facebook
  • LinkedIn
  • WhatsApp
  • E-mail
  • Twitter
time4digital S.à r.l.

2C, op der Gare
L-6850 Manternach

Telefon: + 352 29 20 21

Über uns

Die Firma time4digital SARL ist spezialisiert auf die Entwicklung spezifischer Software Lösungen in Form von Web- und mobile Anwendungen.

Kontaktieren Sie uns!
Legales
  • Impressum
  • Datenschutz
  • Cookie Consent

    Privatsphäre-Einstellungen ändern
Gehe zu
  • Home
  • Über uns
  • Services
  • Portfolio
  • Unser Team
  • Kontakt

© time4digital S.à r.l.

Unsere Webseite verwendet Cookies.

Diese Cookies sind erforderlich für die Funktionalität der Webseite.

Schützt vor Cross-Site-Request-Forgery-Angriffen.

Anbieter: Time4Digital
Speicherdauer: Dieses Cookie bleibt nur für die aktuelle Browsersitzung bestehen.

Speichert die aktuelle PHP-Sitzung.

Anbieter: Time4Digital
Speicherdauer: Dieses Cookie bleibt nur für die aktuelle Browsersitzung bestehen.

Diese Cookies sind optional und beeinträchtigen die Funktionalität der Webseite nicht.

Dieser Cookie steht im Zusammenhang mit Google Universal Analytics - einer bedeutenden Aktualisierung des häufiger verwendeten Analysedienstes von Google. Dieses Cookie wird verwendet, um eindeutige Nutzer zu unterscheiden, indem eine zufällig generierte Nummer als Kundenkennung zugewiesen wird. Es ist in jeder Seitenanforderung auf einer Website enthalten und wird zur Berechnung von Besucher-, Sitzungs- und Kampagnendaten für die Analyseberichte der Website verwendet.

Anbieter: Google
Speicherdauer: 1 Jahr 1 Monat

Dieses Cookie wird von Google Analytics verwendet, um den Sitzungsstatus zu erhalten.

Anbieter: Google
Speicherdauer: 1 Jahr 1 Monat