Leider sind im Contao-Handbuch bis heute keine Beispiele für die Verwendung der Callbacks enthalten. Vor ca. 3 Jahren habe ich hierzu einen Text eingereicht. Es gab zu dem Thema auch ein Diskussion auf GitHub, aber leider ist es nicht zu einer Veröffentlichung gekommen. Da ich beinahe täglich mit den Callbacks arbeite, finde ich eine Übersicht mit Beispielen eine große Erleichterung. Für alle denen es ähnlich geht, stelle ich hier meine Aufstellung zur Verfügung.
Aktionscallbacks
button_callback
Ermöglicht individuelle Navigationssymbole und wird z.B. in der Seitenstruktur verwenden, um Icons abhängig von den Benutzerrechten zu deaktivieren (erfordert eine zusätzliche Prüfung mittels load_callback).
Dieser Aktionscallback wird folgendermaßen in die Definition der Operationen eingefügt:
Die Klasse, die den Callback verarbeitet kann dann zum Beispiel so aussehen:
label_callback
Ermöglicht individuelle Bezeichnungen in der Listenansicht und wird z.B. im Benutzer-Modul verwendet, um die Status-Icons hinzuzufügen.
Dieser Aktionscallback wird folgendermaßen in die Definition des Labels eingefügt:
Die Klasse, die den Callback verarbeitet kann dann zum Beispiel so aussehen:
Auflistungscallbacks
child_record_callback
Legt fest, wie die Kindelemente im "Parent View" dargestellt werden.
Dieser Auflistungscallback wird folgendermaßen in die Definition der Sortierung eingefügt:
Die Klasse, die den Callback verarbeitet kann dann zum Beispiel so aussehen:
group_callback
Ermöglicht individuelle Gruppennamen in der Listenansicht.
(Wird im Contao-Core scheinbar nicht verwendet, leider habe ich kein Beispiel gefunden!)
paste_button_callback
Ermöglicht individuelle Einfüge-Schaltflächen und wird z.B. in der Seitenstruktur verwenden, um die Icons abhängig von den Benutzerrechten zu deaktivieren (erfordert eine zusätzliche Prüfung mittels load_callback).
Dieser Auflistungscallback wird folgendermaßen in die Definition der Sortierung eingefügt:
Die Klasse, die den Callback verarbeitet kann dann zum Beispiel so aussehen:
Feldcallbacks
input_field_callback
Ermöglicht das Erstellen individueller Formularfelder und wird z.B. im Backend-Modul "Persönliche Daten" verwendet, um das "Daten bereinigen"-Feld zu erstellen. Achtung: Eingaben werden nicht automatisch gespeichert!
Dieser Feldcallback wird folgendermaßen in die Felddefinition eingefügt:
Die Klasse, die den Callback verarbeitet kann dann zum Beispiel so aussehen:
load_callback
Wird bei der Initialisierung eines Formularfeldes ausgeführt. Ermöglicht z.B. das Laden eines Standardwertes.
Dieser Feldcallback wird folgendermaßen in die Felddefinition eingefügt:
Die Klasse, die den Callback verarbeitet kann dann zum Beispiel so aussehen:
options_callback
Ermöglicht das Befüllen eines Drop-Down-Menüs oder einer Checkbox-Liste mittels einer individuellen Funktion. Kann z.B. für bedingte Fremdschlüssel-Relationen verwendet werden.
Dieser Feldcallback wird folgendermaßen in die Felddefinition eingefügt:
Die Klasse, die den Callback verarbeitet kann dann zum Beispiel so aussehen:
save_callback
Wird beim Abschicken eines Feldes ausgeführt. Ermöglicht z.B. das Hinzufügen einer individuellen Prüfung.
Dieser Feldcallback wird folgendermaßen in die Felddefinition eingefügt:
Die Klasse, die den Callback verarbeitet kann dann zum Beispiel so aussehen:
Globale Callbacks
oncopy_callback
Wird ausgeführt nachdem ein Datensatz dupliziert wurde. Hinzugefügt in Version 2.8.2.
Dieser Callback wird folgendermaßen in die DCA-Definition eingefügt:
Die Klasse, die den Callback verarbeitet kann dann zum Beispiel so aussehen:
oncut_callback
Wird ausgeführt nachdem ein Datensatz verschoben wurde. Hinzugefügt in Version 2.8.2.
Dieser Callback wird folgendermaßen in die DCA-Definition eingefügt:
Die Klasse, die den Callback verarbeitet kann dann zum Beispiel so aussehen:
ondelete_callback
Wird ausgeführt bevor ein Datensatz aus der Datenbank entfernt wird.
Dieser Callback wird folgendermaßen in die DCA-Definition eingefügt:
Die Klasse, die den Callback verarbeitet kann dann zum Beispiel so aussehen:
onload_callback
Wird bei der Initialisierung des DataContainer-Objekts ausgeführt. Ermöglicht z.B. das Prüfen von Zugriffsrechten oder die dynamische Änderung des Data Container Array zur Laufzeit.
Dieser Callback wird folgendermaßen in die DCA-Definition eingefügt:
Die Klasse, die den Callback verarbeitet kann dann zum Beispiel so aussehen:
onsubmit_callback
Wird beim Abschicken eines Backend-Formulars ausgeführt. Ermöglicht z.B. die Modifizierung der Formulardaten, bevor diese in die Datenbank geschrieben werden (wird in der Kalender-Erweiterung zur Intervalberechnung eingesetzt).
Dieser Callback wird folgendermaßen in die DCA-Definition eingefügt:
Die Klasse, die den Callback verarbeitet kann dann zum Beispiel so aussehen:
Kommentare
Kommentar von Andreas Fieger |
Danke für den Post!
Type: im zweiten Listing: $this-addToUrl($href) muss $this->addToUrl($href) sein (es fehlt das '>').
Antwort von Patrick Froch
Danke für den Hinweis. Das ">" war schon da, leider hat es der SyntaxHighlighter verschluckt. Nun sollte es aber angezeigt werden.
Kommentar von Daniel Jahnsmüller |
Sehr schade das ich erst jetzt drauf stoße. Mich stört auch schon immer die ungenaue Dokumentation und ich schau am Ende immer im Quelltext.
Vielen Dank Patrick! Lesezeichen ist gesetzt.
Kommentar von Mario |
Sehr schöne Auflistung. Danke! :)
Allerdings fehlen einige Callbacks, z.B. der oncreate oder oncreate_version callback. Vielleicht kannst du die noch ergänzen?
Antwort von Patrick Froch
Hallo Mario,
danke für den Hinweis. Als der Artikel entstanden ist, gab es diese Callbacks noch nicht. Insgesamt ist dieser Blog ja quasi mein digitales Gedächtnis. Wenn ich die neuen Callbacks benötige, werde ich die Funktionsweise bestimmt auch hier niederschreiben.
Viele Grüße,
Patrick
Kommentar von Christian Mette |
Ja! Prima Auflistung und immer noch aktuell und praxisrelevant! Vielen Dank!
Der bis heute (meiner Kenntnis nach) wenig oder nicht dokumentierte (seit 2.8) panel_callback zum Generieren von benutzerdefinierten Input-Elementen in einem eigenen Filter-Panel könnte noch ergänzt werden. Position und Aufruf:
list.sorting.panel_callback => ['myFilterName' => ['myClass', 'buildMyFilterInput']] # es kann viele benutzerdefinierte Filter-Felder geben
Signatur:
public function buildMyFilterInput(\DataContainer $dc) {
...
return $html; # returns the filter as html string
}
Das ganze muß noch mit einem eigenen onload_callback kombiniert werden, um die Filter bei jedem Laden zu aktivieren. Der Handler könnte so aussehen:
public function applyAdvancedFilters()
{
# die Session holen
$session = Session::getInstance()->getData();
# testen, ob ein POST gesendet wurde und ob das $_POST vom Filter FORM_SUBMIT kommt
if(isset($_POST) && \Input::post('FORM_SUBMIT')=='tl_filters') {
# wenn ja, hole den Select Value
$postedTimerange = \Input::post('timerange');
# geänderten Wert in der Session merken
$session['filter'][$this_table]['timerange'] = $postedTimerange;
}
# Session wieder schreiben
Session::getInstance()->setData($session);
# Ergebnismenge = Array aus Datensatz-IDs vorbereiten
$arrProjectEventIDs = [0];
# hole alle für diese Tabelle/Ansicht gespeicherten Filter
foreach ($session['filter'][$this_table] as $k => $v) {
# jetzt für jeden Filter ein WHERE bilden
switch ($k) {
# wir haben nur einen Filter
case 'timreange':
switch ($v) {
case 0: # hole alle Datensätze
$where = " WHERE id is not NULL";
break;
case 1: # bis heute
$where = " WHERE startDate <= " . time();
break;
case 2: # nur heute
$where = " WHERE startDate = " . time();
break;
case 3: # ab heute
$where = " WHERE startDate >= " . time();
break;
case 4: # nächste Woche
$where = " WHERE startDate >= " . strtotime("monday");
break;
case 5: # 1. Tag nächster Monat 00:00 Uhr - das Doppelte strtotime setzt auf 00:00 Uhr
$where = " WHERE startDate >= " . strtotime(date('d.m.Y',strtotime("first day of next month")));
break;
case 6:
$where = " WHERE startDate >= " . mktime(0, 0, 0, 1, 1, intval(date("Y", strtotime("+1 year"))));
break; # Neujahrstag nächstes Jahr
default:
$where = "";
break;
}
# jetzt die Abfrage ausführen
$dbResult = \Database::getInstance()->prepare("SELECT id FROM mytable $where")->execute();
# alle IDs der Treffer in das Array laden
$arrProjectEventIDs = $dbResult->fetchEach('id');
break;
default:
break;
}
}
# dieses Konstrukt verhindert den Fehler:
# An exception occurred while executing 'SELECT DISTINCT `field` FROM child_table WHERE pid='nn' AND id IN()'
# denn IN() wird durch das Array abgebildet, daher muss das Array mindestens einen Wert enthalten, hier [0]
if (is_array($arrProjectEventIDs) && empty($arrProjectEventIDs)) {
$arrProjectEventIDs = [0];
}
# die IDs setzen, so dass nur diese Datensätze aufgelistet werden
$GLOBALS['TL_DCA'][$this_table]['list']['sorting']['root'] = $arrProjectEventIDs;
}
Viel Spaß!
Antwort von Patrick Froch
Vielen Dank für den Hinweis. Eine sehr interessanter Callback. Ich lasse ihn hier im Kommentar, so ist auch die Quelle ersichtlich.
Einen Kommentar schreiben