AddOn-Entwicklung #3 - Rex_list und Rex_form

Wir werden die REDAXO-eigene Klasse rex_list() verwenden, um die Inhalte der beiden Tabellen (Adressen und Gruppen) aufzulisten.

Zunächst prüfen wir in der gruppen.inc.php, ob die get-Variable $func gesetzt ist. Wenn sie keinen Wert enthält (sich also nicht im Editiermodus befindet), soll die Listenansicht ausgegeben werden.

Mit dem Select-Kommando können wir die Werte aus der Tabelle rex_553_gruppen holen und diese nach dem Gruppennamen sorieren:

<?php
if ($func == '') {

$list = rex_list::factory('SELECT id, gruppe from '.$REX['TABLE_PREFIX'].'553_gruppen order by gruppe');

$imgHeader = '<a href="'. $list->getUrl(array('func' => 'add')) .'"><img src="media/metainfo_plus.gif" alt="add" title="add" /></a>';

$list->addColumn(
$imgHeader, '<img src="media/metainfo.gif" alt="field" title="field" />', 0, array( '<th class="rex-icon">###VALUE###</th>', '<td class="rex-icon">###VALUE###</td>' )
);

$list->setColumnLabel('id', 'ID');
$list->setColumnLabel('gruppe', 'Gruppe');
$list->setColumnParams('gruppe', array('func' => 'edit', 'id' => '###id###'));

$list->show();
}
?>

Sehen wir uns den Code nach dem Select-Befehl näher an. In der Variable $imgHeader definieren wir einen Image-Link, mit dem ein neuer Datensatz hinzugefügt werden kann. $func wird mit diesem Link auf den Wert “add” gesetzt wird, hier würde also nach einem Klick auf den add-Link auch keine Liste angezeigt werden. Als Icon wird eines der System-Icons verwendet, man könnte hier natürlich auch ein eigenes verwenden.

Normalerweise werden alle Felder aus der Select-Abfrage (in unserem Beispiel also id und gruppe) gelistet. Mit $list->addColumn fügen wir jedoch der Liste zu Beginn eine Spalte hinzu. Der erste Wert der Funktion definiert den Spaltentitel (hier ein Icon), der zweite Wert den Text aller Folgezeilen (ebenfalls ein Icon). Der dritte Wert legt die Position fest, an der die neue Spalte erscheinen soll, mit 0 also ganz am Anfang. Das Array im vierten Wert legt die Formatierung, bzw. den HTML-Output fest: ein th-Tag für den Spaltentitel, ein td-Tag für alle folgenden Listenzeilen.

Die beiden folgenden Aufrufe sind optional. Wir können damit steuern, wann welche Felder der Datenbank aufgelistet werden und was als Spaltentitel darüber steht. Würden wir diese Zeilen weglassen, so werden einfach alle im SQL-Select ausgewählten Felder in der Reihenfolge ihres Ausrufs ausgegeben; als Überschrift dient dann schlicht der Feldname.

Falls wir ein Feld – obwohl im SQL-Kommando ausgewählt – von der Ausgabe ausschließen möchten, so muss man dies explizit angeben mit:

$list->removeColumn('feldname');

AddOn in sieben Schritten

EXKURS Mehrsprachigkeit

Wenn man ein Backend mehrsprachig gestaltet, muss man natürlich alle Feldbezeichnungen und Spaltentitel auch mehrsprachig steuern. Wir erreichen dies, indem wir alle Ausgaben mit I18N und der in der config-Datei angelegten Sprachinstanz $I18N_adressen steuern; statt Gruppe müssten wir also $I18N_adressen->msg('gruppe') schreiben. Die Übersetzungen steuert man in den Sprachdateien innerhalb des lang-Ordners unseres Addon-Verzeichnisses.

Pro unterstützter Sprache muss dort eine .lang-Datei angelegt werden, in der wir alle Übersetzungen eintragen. Achtung: Wie im Backend auch benötigt die UTF-Version eine eigene Datei, Beispiele wären also de_de_utf8.lang oder en_us.lang.

gruppe = Gruppe
plz = Postleitzahl
email = Email-Adresse
...

Durch $I18N_adressen->msg(&#039;gruppe&#039;) wird also dann im Browser je nach Sprache “Postleitzahl” oder ZIP-Code ausgegeben.

Der Einfachheit halber verzichten wir aber im Workshop auf Mehrsprachigkeit.

Zurück zum Thema

Die Funktion setColumnParams dient dazu, einen Link auf die Werte dieser Spalte zu legen und erwartet als zweiten Parameter ein Array, mit dem man einen Link beliebiger Länge zusammenbauen könnte. Unser Beispiel hängt also folgende Parameter an den Link: page=adressen&subpage=gruppen&func=edit&id=1. Dieser Link würde den Datensatz mit der ID 1 zum Editieren öffnen.

Die Auflistung der Adressen in der Datei adressen.inc.php erfolgt nach identischem Schema. Dort wollen wir allerdings noch folgende Zeilen einfügen:

$list->setColumnSortable('name');
$list->setColumnSortable('vorname');
$list->setColumnSortable('plz');

Man kann vielleicht schon erahnen, was wir damit erreichen: Die Titel der Spalten name, vorname und plz erhalten einen Link; ein Klick sortiert die gesamte Tabelle absteigend nach dieser Spalte; ein erneuter Klick ändert die Sortierung auf ansteigend. Ein ebenfalls sehr praktisches Steuerungsinstrument erhält man, wenn man hinter das Select-Kommando, getrennt mit einem Komma, eine Zahl wie etwa 50 hinzufügt. Damit werden immer nur 50 Datensatz-Zeilen pro Seite dargestellt. Existieren mehr, erscheinen automatisch Links zum Vor- und Zurückbättern. Der Defaultwert liegt übrigens bei 30.

Rex_form – Datensätze mit Formularfeldern verändern

Noch können wir keine Datensätze verändern oder neue anlegen. Deshalb arbeiten wir nun die Prüfung der Variable $func weiter aus, diesmal am Beispiel der Adressen-Tabelle. Statt der schließenden Klammer führen wir die If-Bedingung fort, für den Fall, dass $func mit dem Wert add oder edit belegt ist:

elseif ($func == 'edit' || $func == 'add') {
$form = rex_form::factory($REX['TABLE_PREFIX'].'_553_adressen',"Adressen","id=".$id);
$field = &$form->addTextField('name');
$field->setLabel('Name');
$field = &$form->addTextField('vorname');
$field->setLabel('Vorname');
// dito für alle anderen Felder

$field = &$form->addSelectField('status');
$field->setLabel('Status');$select =& $field->getSelect();
$select->setSize(1);
$select->addOption('Online',1);
$select->addOption('Offline',0);
$select->setAttribute('style','width: 100px');
// Standardwert: 1
if ($field->getValue()== "") {
$field->setValue(1);
}

// Selectfeld für Gruppen
$field = &$form->addSelectField('r_gruppe');
$field->setLabel('Gruppe');
$select = &$field->getSelect();
$select->setSize(1);
$query = 'SELECT gruppe as label, id FROM '.$REX['TABLE_PREFIX'].'553_gruppen';
$select->addSqlOptions($query);
if($func == 'edit') {
$form->addParam('id', $id);
}
$form->show();
}

AddOn in sieben Schritten

Mit der neuen Instanz der Klasse rex_form() wird der Datensatz mit der in der URL übermittelten ID aus der Datenbank geholt. Danach legen wir nach und nach alle Formular-Felder nach dem gleichen Schema an. Zur Verfügung stehen alle in Formularen üblichen Felder, also neben Funktionen wie addTextField() natürlich auch addCheckboxField(), addRadioField() oder addSelectField(), aber auch die REDAXO-eigenen Felder addMediaField() für den Zugriff auf den Medienpool oder addLinkmapField() zum Setzen eines internen Links. Je nach Feld können wir weitere Attribute nutzen. Mit setLabel etwa definieren wir die Feldbeschriftung. Und beim Selectfeld können wir mit setSize die Größe bestimmen und mit setAttribute weitere Tag-Attribute, wie z.B. CSS-Formatierungen festlegen.

Selectfelder sind auch sehr hilfreich, wenn die einzelnen Optionen dynamisch aus einer anderen Tabelle gelesen werden. Und genau das benötigen wir, wenn wir den Adressen eine bestimmte Gruppe aus der Gruppentabelle zuweisen wollen. In REDAXO existiert dafür die Funktion addSqlOptions($query). $query muss vorher mit einer SQL-Abfrage gefüllt werden, wobei zuerst das Feld gewählt wird, das den Text der jeweiligen Option liefert, danach das Feld, das den zu speichernden Wert bereitstellt. Die Auswahlliste des Selectfeldes wird also aus der Tabelle rex_533_gruppe entnommen; gespeichert wird die ID der Gruppe im Feld r_gruppe der Adresstabelle.

Man könnte noch mit wenigen Codezeilen ein Suchfeld hinzufügen, um im Backend nach einem bestimmten Namen oder einer PLZ zu filtern, doch wir wollen an dieser Stelle die Arbeiten an der Verwaltung beenden. Man sieht, dass man mit ein wenig Übung in ca. 20 Minuten die komplette Backend-Verwaltung für unsere Adress-Datenbank erstellt hat.

Hinweis

Sicher – mit den REDAXO-eigenen Klassen und Methoden von rex_list() und rex_form() kann man die allermeisten Probleme lösen. Aber manchmal reichen sie dennoch nicht aus. Kein Problem: Wir können selbstverständlich auch eigene ergänzen oder die bestehenden erweitern – dann muss man diese in der config-Datei Ihres AddOns includen:

include_once ($REX['INCLUDE_PATH'].'/addons/adressen/class.meine_eigene_klasse.inc.php');

Weiter zum Teil 4 - Frontend-Ausgabe

Zurück zum Teil 2 - Anatomie eines AddOns