Contao Module erstellen – DCA

Nun kommen wir zum Data Container Array, kurz DCA. Wie bereits im letzten Artikel „Contao Module erstellen – Backend“ beschrieben, geht es vorerst um den Backend-Teil. Wir haben dort eine Tabelle tl_customers definiert und nun müßen wir Contao noch die DCA dazu liefern. Unter $GLOBALS[‚TL_DCA‘] sind diese Tabellen-Metadaten hinterlegt. Wir erstellen also im Ordner shop/dca eine Datei tl_customers.php. Dort können wir die globalen Variablen $GLOBALS respektive unter dem Schlüssel $GLOBALS[‚TL_DCA‘][‚tl_customers‘] mit der Definition beginnen.

Die Referenz zu der DCA findet sich unter „Interne Struktur eines Data Containers“ auf der Contao Seite.

Meine DCA sieht folgendermaßen aus:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Data Container Array Definition für Tabelle
// tl_customers
$GLOBALS['TL_DCA']['tl_customers'] = array
(
 // Allgemein Konfiguration
 'config' => array
 (
 // Table (Tabellen), File (lokale Konfigurations-
 // datei) oder Folder (Dateiverwaltung).
 'dataContainer'               => 'Table',
 // Aktiviert die "Speichern und Bearbeiten"-
 // Schaltfläche beim Anlegen eines neuen Daten-
 // satzes (nur Sortierungsmodus 4).
 'switchToEdit'                => true
 ),
 
 // Alle Einstellungen, die für die Auflistung bzw.
 // Manipulation von Datensätzen benötigt werden.
 // Wir können hier die Sortierung, das Layout
 // (z. B. Filter, Suche, Einschränkungen)
 // Beschriftungen und Operationen bestimmen.
 'list' => array
 (
 // Sortierung
 'sorting' => array
 (
 'mode'                    => 1,
 // Sortierung nach name
 'fields'                  => array('name'),
 // Kategorisierung
 'flag'                    => 1,
 // Layout
 'panelLayout'             => 'search,limit'
 ),
 
 // Beschriftung
 'label' => array
 (
 'fields'                  => array('name'),
 'format'                  => '%s',
 // Callback für die Beschriftung
 'label_callback'          => array('tl_customers', 'addCustomer')
 ),
 'global_operations' => array
 (
 'all' => array
 (
 'label'               => &$GLOBALS['TL_LANG']['MSC']['all'],
 'href'                => 'act=select',
 'class'               => 'header_edit_all',
 'attributes'          => 'onclick="Backend.getScrollOffset();"'
 )
 ),
 
 'operations' => array
 (
 'edit' => array
 (
 'label'               => &$GLOBALS['TL_LANG']['MOD']['tl_customers']['edit'],
 'href'                => 'act=edit',
 'icon'                => 'edit.gif',
 ),
 'copy' => array
 (
 'label'               => &$GLOBALS['TL_LANG']['MOD']['tl_customers']['copy'],
 'href'                => 'act=copy',
 'icon'                => 'copy.gif',
 ),
 'delete' => array
 (
 'label'               => &$GLOBALS['TL_LANG']['MOD']['tl_customers']['delete'],
 'href'                => 'act=delete',
 'icon'                => 'delete.gif',
 'attributes'          => 'onclick="if (!confirm(\'' .
    $GLOBALS['TL_LANG']['MSC']['deleteConfirm'] . '\'))
    return false; Backend.getScrollOffset();"',
 ),
 'show' => array
 (
 'label'               => &$GLOBALS['TL_LANG']['MOD']['tl_customers']['show'],
 'href'                => 'act=show',
 'icon'                => 'show.gif'
 )
 ),
 ), // list end
 
 'palettes' => array
 (
 'default'                     => '{title_legend},customernumber,name,email'
 ),
 
 'fields' => array
 (
 // Felder, die im Backend angezeigt werden sollen.
 'customernumber' => array
 (
 'label'                   => &$GLOBALS['TL_LANG']['MOD']['tl_customers']['customernumber'],
 'inputType'               => 'text',
 'search'                  => true,
 'eval'                    => array('mandatory'=>true, 'maxlength'=>5)
 ),
 'name' => array
 (
 'label'                   => &$GLOBALS['TL_LANG']['MOD']['tl_customers']['name'],
 'inputType'               => 'text',
 'search'                  => true,
 'eval'                    => array('mandatory'=>true, 'maxlength'=>255)
 ),
 'email' => array
 (
 'label'                   => &$GLOBALS['TL_LANG']['MOD']['tl_customers']['email'],
 'inputType'               => 'text',
 'search'                  => true,
 'eval'                    => array('mandatory'=>true, 'maxlength'=>128,
                              'rgxp'=>'email', 'decodeEntities'=>true,
                              'tl_class'=>'w50')
 ),
 )
);

Im Backend haben wir nun folgendes vorliegen:

Ein Beispiel unseres Modules im Backend

 

Am wichtigsten ist ein ständiger Blick auf die Contao Referenz. Damit die Texte korrekt angezeigt werden, müssen wir natürlich auch passende Übersetzungen angelegt haben.

1. Update

Ich will zu jedem Kunden ein Mitglied verknüpfen (tl_member, 1:1 Relation). Um das in Contao umzusetzen sind folgende Schritte notwendig:

  1. Tabelle um eine Spalte cuser erweitern:
    `cuser` INT(10) UNSIGNED NOT NULL DEFAULT '0'
  2. Installationstool aufrufen und Änderung einspielen.
  3. Die DCA anpassen. Im Feldarray (fields) müssen wir folgende Ergänzung machen:
    'cuser' => array
     (
     'label'                   => &$GLOBALS['TL_LANG']['MOD']['tl_customers']['cuser'],
     'default'                 => $GLOBALS['TL_CONFIG']['defaultUser'],
     'exclude'                 => true,
     'inputType'               => 'select',
     'foreignKey'              => "tl_member.CONCAT(firstname, ' ', lastname)",
     'eval'                    => array('mandatory'=>true,
                                  'unique'=>true, 'includeBlankOption'=>true,
                                  'tl_class'=>'w50'),
     ),

    Sehr interessant dürfte die Zeile mit dem Schlüssel foreignKey sein. Normalerweise kann hier nur eine Spalte angegeben werden, die für die Auswahlbox als Anzeigetitel verwendet wird. Mit diesem kleinen Trick kann quasi jede Kombination realisiert werden und mehrere Werte bzw. Spalten für den foreignKey bestimmt werden. Man muß sich nur im klaren sein, dass die SQL-Anweisung CONCAT nicht von jeder Datenbank verstanden wird. Als Ergebnis erhält man folgendes:

Das wars dann auch schon. Einzig zu erwähnen ist, dass unique=>true notwendig ist, um die 1:1 zu simulieren bzw. keine Mitglied mehrfach einem Shop-Kunden zuweisen zu können.

6 Gedanken zu “Contao Module erstellen – DCA

  1. Hallo

    Wie lässt sich denn die Darstellung im Backend ändern. Ich möchte bspw. eine Auflistung aller Artikel – nur eine Liste mit den Artikeln, ohne Menüstruktur. Eine Idee? Ich komm‘ da nicht wirklich weiter. Danke bereits im Voraus! :)

    • Schau dir die DCA-Referenz von Contao an: . Dort steht „Das Auflistungsarray legt fest, wie Datensätze aufgelistet werden. Die Contao Core-Engine unterstützt drei Ansichen: den List View, den Parent View und den Tree View“…

  2. Hi,
    also bei mir funzt das irgendwie nicht – ich konnte zwar Datensätze anlegen, allerdings sobald ich die Liste wieder aufrufen möchte erhalte ich folgenden Fehler:

    Fatal error: Could not load class tl_customers in /html/contao/system/functions.php on line 104

    Weißt Du was das sein könnte?

    VG
    Robert

    • Hallo Robert,

      schwer zu sagen ohne Code. Aber ich denke, du hast das Beispiel oben einfach so kopiert. Dort wird nämlich ein Label-Callback definiert: ‚label_callback‘ => array(‚tl_customers‘, ‚addCustomer‘). Die Klasse tl_customers wird es bei dir wohl nicht geben. Nimm die Zeile einfach raus. Grüße

Kommentar verfassen