Ein Blick in ein Contao-Widget

Heute will ich das TextField betrachten. Ich möchte in einem Modul ein einfaches Formular umsetzen und natürlich will ich wenn möglich bestehenden Code wiederverwenden. Eine Textbox möchte ich mit dem Widget TextField umsetzen. Soweit ich das verstanden habe ist ein “Widget” in Contao ein Element in einem Formular. Im Klassenkommentar der abstrakten Klasse Widget steht: “Provide methods to handle form widgets”. Wie sieht TextField nun aus und wie kann es verwendet werden?

Continue reading

Klassen in Contao überschreiben

Um Klassen in einem Contao Modul zu überschreiben, wird in der config/config.php die eigene Klasse registriert:

$GLOBALS['FE_MOD']['navigationMenu']['navigation'] = ModuleMeineUeberschriebeneNavigationKlasse

Wir wollen ja eine bestehende Klasse erweitern, deswegen muß sich der Eintrag mit einem bestehenden Modul decken. Am besten schaut man dazu in das entsprechende Modul. Anschließend definiert man die Klasse im eigenen Modul-Ordner. Bitte darauf achten, dass der Ordner im Alphabet nach dem zu überschreibenden Modul kommt, da Contao die Module in alphabetischer Reihenfolge einliest. Die Klasse selbst leitet dann von der bereits vorhandenen Klasse ab:

class ModuleMeineUeberschriebeneNavigationKlasse extends ModuleNavigation
{
  // Hier wird Funktionalität überschrieben / erweitert
}

Contao Frontend Module – Einstieg

Die Erstellung eines Frontend-Moduls in Contao ähnelt sehr dem eines Backend-Moduls. Im Ordner config des Moduls liegt die Datei config.php. Dort wird die Definition von Backend- und Frontend-Modulen vorgenommen. Wir fügen mit array_insert einen neuen Eintrag in das globale Konfigurationsarray hinzu:

/**
 * Definition eines Frontend Moduls
 */
array_insert($GLOBALS['FE_MOD'], 3, array
(
	'meineKategorie' => array
	(
		'meinFrontendModul'   => 'ModuleMeineFrontendKlasse',
	)
));

Die Funktion array_insert ist übrigens eine Contao-Funktion, die Werte (darunter fallen auch Arrays) in ein Array einfügen kann. Für die zwei Array-Schlüssel sind noch zwei Übersetzungen ganz nützlich. Diese werden beispielsweise unter languages/de/modules.php vorgenommen:

/**
 * Frontend Modul Übersetzungen
 */
$GLOBALS['TL_LANG']['FMD']['meineKategorie']   = 'Meine Kategorie';
$GLOBALS['TL_LANG']['FMD']['meinFrontendModul']= array('Mein Frontend Modul Titel', 'Eine Beschreibung');

In Contao gibt es leider einen Mix zwischen zwischen einfachen String- und Array-Übersetzungen. An dieser Stelle muß man sich leider an bereits bestehenden Modulen orientieren.

Nun fehlt noch eine passenden PHP-Klasse und ein Template für das Modul. Die Frontend-Modul-Klasse wird direkt im Wurzelverzeichnis des Moduls erstellt und leitet von der abstrakten Contao-Klasse Module ab. Einzige abstrakte Methode, die wir implementieren müssen ist compile(). Diese Methode wird wiederum aus der Methode generate() aufgerufen. Prinzipiell ist es dem Entwurfsmuster Strategie sehr ähnlich, leider ist die generate-Methode nicht final und der Entwickler kann somit die generate-Methode überschreiben und den parent-Aufruf vergessen. In diesem Fall wird das Frontend-Modul nichts anzeigen. Ein absolutes Grundgerüst sieht folgendermaßen aus:

class ModuleMeineFrontendKlass extends Module
{
  /**
   * Template
   * @var string
   */
  protected $strTemplate = 'mod_mein_template';
 
  protected function compile()
  {
    $this->Template->hallo = 'Hallo World';
  }
}

Die Variable $strTemplate beinhaltet das Template für unser kleines Frontend-Modul (ohne Erweiterung tpl). In der konkreten Implementierung unserer compile-Methode befindet sich eine Wertzuweisung zur Template-Engine. Im Template kann auf diese Variablen schließlich zugegriffen werden.

Das Template selbst ist ebenfalls recht überschaubar:

<!-- indexer::stop -->
<div class="<?php echo $this->class; ?> block"
  <?php echo $this->cssID; ?>
  <?php if ($this->style): ?> style="<?php echo $this->style; ?>"<?php endif; ?>>
 
  <?php echo $this->hallo; ?>
 
</div>
<!-- indexer::continue -->

Die zwei Kommentare oben und unten verhindern, dass die Ausgaben in diesem Template nicht durch die Suche indiziert, also nicht durch die Suche gefunden werden. Anschließend wird der Inhalt unserer zuvor definierten Variable hallo ausgegeben. In dem umschließenden DIV werden noch Klassen, eine ID und ggf. CSS-Anweisungen ausgegeben. Diese werden in der Oberklasse Module in der Methode generate() registriert. Beispielsweise enthält $this->style den oberen und unteren Abstand (margin), den man im Backend standardmäßig festlegen kann.