C3: Tutorial Extension Entwicklung 1.Teil: Grundlagen: Unterschied zwischen den Versionen
Aus Contao Community Documentation
(→Die Übersetzung für das FE-Template erstellen (Video 44:00)) |
|||
(62 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
[[Category:Dev HOWTOS]] | [[Category:Dev HOWTOS]] | ||
− | |||
− | |||
=Einleitung= | =Einleitung= | ||
− | Seit 2010 arbeite ich nun schon mit Contao. Vorher habe ich die CMS Joomla, Typo3 und Drupal ausprobiert und muss sagen: Contao rocks! Leider hat das CMS aus meiner Sicht jedoch einen entscheidenden Nachteil gegenüber anderen Systemen: Es gibt | + | Seit 2010 arbeite ich nun schon mit Contao. Vorher habe ich die CMS Joomla, Typo3 und Drupal ausprobiert und muss sagen: Contao rocks! Leider hat das CMS aus meiner Sicht jedoch einen entscheidenden Nachteil gegenüber anderen Systemen: Es gibt nur wenige Tutorials, die "semiprofessionellen" Programmierern einen schrittweisen und zusammenhängenden Einstieg in die Extension-Entwicklung mit Contao 3 anhand eines Praxisbeispiels ermöglichen. |
− | + | Die Screencast-Reihe von '''Tristan Lins auf Youtube''' stellt dabei eine Ausnahme dar. Ich persönlich mag es aber, Tutorials auch in geschriebener Form vor mir zu haben. Daher habe ich damit begonnen, die Videos in dieses Wiki zu übertragen. Viel Spaß damit! | |
+ | Videolink: [http://www.youtube.com/watch?v=WeN5a0R9asQ&feature=share&list=PL3mn8AtCRAstvuAWY8dhrHisMYapPxOnt Basics - der Contao Aufbau, DCA] | ||
==An wen richtet sich dieses Tutorial?== | ==An wen richtet sich dieses Tutorial?== | ||
Dieses Tutorial ist für all diejenigen gedacht, die ein Step-by-Step Tutorial zum Einstieg in die Extension-Entwicklung mit Contao 3 suchen. | Dieses Tutorial ist für all diejenigen gedacht, die ein Step-by-Step Tutorial zum Einstieg in die Extension-Entwicklung mit Contao 3 suchen. | ||
Zeile 14: | Zeile 13: | ||
In diesem Tutorial lernt ihr die Grundlagen der Extension-Entwicklung mit Contao 3 anhand eines praktischen Beispiels. Es wird ein Modul programmiert, welches verschiedene Screencast-URLs inkl. Titel auflistet. | In diesem Tutorial lernt ihr die Grundlagen der Extension-Entwicklung mit Contao 3 anhand eines praktischen Beispiels. Es wird ein Modul programmiert, welches verschiedene Screencast-URLs inkl. Titel auflistet. | ||
− | + | '''So sieht das fertige Modul aus:''' | |
+ | |||
+ | [[Datei:T1_fertigesModul.jpg|Fertiges Modul]] | ||
==Was man wissen sollte== | ==Was man wissen sollte== | ||
Zeile 25: | Zeile 26: | ||
''contao/system/modules'' | ''contao/system/modules'' | ||
angelegt werden: | angelegt werden: | ||
+ | |||
[[Datei:T1_vorbereitung.png|Verzeichnisstruktur der Erweiterung]] | [[Datei:T1_vorbereitung.png|Verzeichnisstruktur der Erweiterung]] | ||
− | Zum Verständnis: Im Verzeichnis modules liegen die Module, die bereits von Contao mitgeliefert werden, | + | |
+ | Zum Verständnis: Im Verzeichnis modules liegen die Module, die bereits von Contao mitgeliefert werden, wie z.B. FAQ, Calendar etc. Auch unser Erweiterungsmodul 'screencast' gehört in dieses Verzeichnis. | ||
+ | |||
+ | ==Source-Code== | ||
+ | Den Quellcode könnt ihr hier: | ||
+ | https://github.com/bit3/contao-screencast3 | ||
+ | herunterladen. | ||
+ | {{Hinweis|Es kann sein, dass der Quellcode auf github bereits einer fortgeschritteneren Version entspricht. Passt die Dateien daher ggf. dem Code dieses Tutorials an oder (am besten) programmiert alles selber! }} | ||
=Einen Menüeintrag im Inhaltsbereich der Backend-Module erzeugen.= | =Einen Menüeintrag im Inhaltsbereich der Backend-Module erzeugen.= | ||
− | *Erstellt im Verzeichnis config die Datei config.php. <br/>In der config.php werden z.B. Frontend- und Backend-Module registriert. | + | *Erstellt im Verzeichnis ''config'' die Datei ''config.php''. <br/>In der ''config.php'' werden z.B. Frontend- und Backend-Module registriert. |
− | *Schreibt in die config.php folgenden Code: | + | *Schreibt in die ''config.php'' folgenden Code: |
− | < | + | <source lang="php"> |
+ | <?php | ||
− | Dabei steht ['BE_MOD']['content'] für die Elemente der Backend-Module im Inhaltsbereich (Array). Durch die Erweiterung des Arrays um ['screencast'] wird unser neues Modul referenziert. | + | /** |
+ | * Back end modules | ||
+ | */ | ||
+ | $GLOBALS['BE_MOD']['content']['screencast'] = array( | ||
+ | 'tables' => array('tl_screencast'), | ||
+ | 'icon' => 'system/modules/screencast/assets/images/screencast.png' | ||
+ | ); | ||
+ | </source> | ||
+ | |||
+ | Dabei steht ''['BE_MOD']['content']'' für die Elemente der Backend-Module im Inhaltsbereich (Array). Durch die Erweiterung des Arrays um ''['screencast']'' wird unser neues Modul referenziert. | ||
Als Wert wird dem Array ein assoziatives Array mit zwei Einträgen (Verweis auf die Tabelle in der Datenbank, sowie auf die Bilddatei) übergeben. | Als Wert wird dem Array ein assoziatives Array mit zwei Einträgen (Verweis auf die Tabelle in der Datenbank, sowie auf die Bilddatei) übergeben. | ||
*Fügt in den Ordner ''screencast/assets/images'' ein Icon für euer Modul ein. | *Fügt in den Ordner ''screencast/assets/images'' ein Icon für euer Modul ein. | ||
− | * Da das assets-Verzeichnis geschützt ist, müsst ihr noch eine .htaccess Datei in | + | *Da das assets-Verzeichnis geschützt ist, müsst ihr noch eine ''.htaccess'' Datei in ''screencast/assets/'' speichern. Darin muss stehen: |
− | < | + | <source lang="php"> |
+ | <IfModule !mod_authz_core.c> | ||
+ | Order allow,deny | ||
+ | Allow from all | ||
+ | </IfModule> | ||
+ | <IfModule mod_authz_core.c> | ||
+ | Require all granted | ||
+ | </IfModule> | ||
+ | </source> | ||
+ | |||
+ | Achtung: Hier besteht eine Abweichung vom Screencast, da ab Apache-Version 2.4 die Anweisung anders lauten muss. | ||
Nun soll in der Auflistung der Elemente im Backend-Modul auch eine entsprechende Übersetzung ausgegeben werden. | Nun soll in der Auflistung der Elemente im Backend-Modul auch eine entsprechende Übersetzung ausgegeben werden. | ||
− | + | *Erstellt hierzu ein Verzeichnis ''de'' in eurem Verzeichnis ''screencast/languages/'' | |
− | + | *Erstellt in diesem Verzeichnis eine Datei ''modules.php'' | |
− | + | *In diese Datei gebt ihr folgenden Code ein: | |
− | < | + | <source lang="php"> |
− | + | <?php | |
− | + | ||
− | + | $GLOBALS['TL_LANG']['MOD']['screencast'][0] = 'Screencasts'; | |
− | + | $GLOBALS['TL_LANG']['MOD']['screencast'][1] = 'Screencasts verwalten'; | |
+ | </source> | ||
+ | *Öffnet eure Contao-Backend und navigiert dort zu ''System->Einstellungen'' | ||
+ | *Setzt dort einen Haken unter den ''Sicherheitseinstellungen->Internen Cache'' (ab v 3.1. Globale Einstellungen->Internen Cache umgehen) umgehen. Und <br/>''Sicherheitseinstellungen->Fehlermeldungen'' anzeigen. | ||
+ | *Eure Seitenleiste sollte nach einer Aktualisierung der Seite nun so aussehen: | ||
+ | [[Datei:t1_BE_Module.png|Die Backend-Module sind nun um den Eintrag "Screencasts" erweitert]] | ||
Heureka! Der Eintrag erscheint in der Liste. Leider wirft Contao jedoch nach Klick auf Screencast noch eine Fehlermeldung. | Heureka! Der Eintrag erscheint in der Liste. Leider wirft Contao jedoch nach Klick auf Screencast noch eine Fehlermeldung. | ||
+ | |||
Was fehlt? Contao kann noch kein DCA-Objekt erstellen. | Was fehlt? Contao kann noch kein DCA-Objekt erstellen. | ||
==Was macht ein DCA?== | ==Was macht ein DCA?== | ||
+ | |||
"Data Container Arrays (DCAs) dienen zur Speicherung von Tabellen-Metadaten. Jedes DCA beschreibt die Konfiguration einer bestimmten Tabelle, ihre Beziehungen zu anderen Tabellen sowie die einzelnen Felder. Die Contao Core-Engine erkennt anhand dieser Metadaten, wie Datensätze aufgelistet, bearbeitet und gespeichert werden." | "Data Container Arrays (DCAs) dienen zur Speicherung von Tabellen-Metadaten. Jedes DCA beschreibt die Konfiguration einer bestimmten Tabelle, ihre Beziehungen zu anderen Tabellen sowie die einzelnen Felder. Die Contao Core-Engine erkennt anhand dieser Metadaten, wie Datensätze aufgelistet, bearbeitet und gespeichert werden." | ||
(Quelle: https://contao.org/de/manual/3.0/data-container-arrays.html, Stand: 6.4.13) | (Quelle: https://contao.org/de/manual/3.0/data-container-arrays.html, Stand: 6.4.13) | ||
+ | |||
+ | {{Achtung|Momentan gibt es in Abhängigkeit der Version mehrere DCA-Dokus. Schaut daher bitte vorher, welche Doku für eure Contao Version zutrifft.}} | ||
==Wie ist ein DCA aufgebaut?== | ==Wie ist ein DCA aufgebaut?== | ||
Zeile 64: | Zeile 102: | ||
Neu in Contao 3: In der DCA-Datei werden auch die SQL-Befehle eingetragen. Eine separate Datei ist nicht mehr notwendig. | Neu in Contao 3: In der DCA-Datei werden auch die SQL-Befehle eingetragen. Eine separate Datei ist nicht mehr notwendig. | ||
+ | |||
Alles klar? Nicht? Ok...dann Schritt für Schritt. | Alles klar? Nicht? Ok...dann Schritt für Schritt. | ||
Zeile 69: | Zeile 108: | ||
Erstellt im Verzeichnis ''screencast/dca/'' eine Datei mit Namen ''tl_screencast.php''. | Erstellt im Verzeichnis ''screencast/dca/'' eine Datei mit Namen ''tl_screencast.php''. | ||
− | + | ==Die Tabellenkonfiguartion== | |
+ | |||
Anmerkung: Ab jetzt ist "Mut zur Lücke" gefordert. Einige Sachverhalte sind mir in dem Screencast nicht ganz klar geworden. Leider ist auch die Dokumentation auf Contao.org in diesem Bereich noch recht rudimentär. Ich schreib daher auf, was ich verstanden habe. | Anmerkung: Ab jetzt ist "Mut zur Lücke" gefordert. Einige Sachverhalte sind mir in dem Screencast nicht ganz klar geworden. Leider ist auch die Dokumentation auf Contao.org in diesem Bereich noch recht rudimentär. Ich schreib daher auf, was ich verstanden habe. | ||
− | Auf der Contao-Seite kann man sich über die möglichen Einträge in den DCA informieren. Leider ist hier derzeit noch nicht aufgeführt, welchem Array-Abschnitt welche Einträge zugeordnet sind. Tristan empfiehlt, sich die Verwendungsmöglichkeiten in bestehenden Modulen abzugucken. | + | Auf der Contao-Seite kann man sich über die möglichen Einträge in den DCA informieren. |
+ | https://contao.org/de/manual/3.0/data-container-arrays.html | ||
+ | |||
+ | Leider ist hier derzeit noch nicht aufgeführt, welchem Array-Abschnitt welche Einträge zugeordnet sind. Tristan empfiehlt, sich die Verwendungsmöglichkeiten in bestehenden Modulen abzugucken. | ||
Für die nachfolgenden Erklärungen empfiehlt es sich jedoch trotzdem, den DCA-Teil der Online-Doku aufzufrufen, um scih über die Bedeutung der Arrayeinträge zu informieren. | Für die nachfolgenden Erklärungen empfiehlt es sich jedoch trotzdem, den DCA-Teil der Online-Doku aufzufrufen, um scih über die Bedeutung der Arrayeinträge zu informieren. | ||
− | Wer nicht alles selber schreiben möchte | + | Wer nicht alles selber schreiben möchte, kopiert sich nun erstmal den gesamten Inhalt der Datei ''sytem/modules/core/dca/tl_theme.php'' in die ''tl_screencast.php'' und modifiziert diese nur entsprechend der folgenden Beispiele. |
+ | |||
+ | *Schreibt in die Datei ''tl_screencast.php'' folgende Zeilen Code: | ||
+ | <source lang="php"> | ||
+ | <?php | ||
+ | |||
+ | |||
+ | /** | ||
+ | * Table tl_screencast | ||
+ | */ | ||
+ | $GLOBALS['TL_DCA']['tl_screencast'] = array | ||
+ | ( | ||
− | + | // Config | |
− | < | + | 'config' => array |
+ | ( | ||
+ | 'dataContainer' => 'Table', | ||
+ | 'enableVersioning' => true, | ||
+ | 'sql' => array | ||
+ | ( | ||
+ | 'keys' => array | ||
+ | ( | ||
+ | 'id' => 'primary' | ||
+ | ) | ||
+ | ), | ||
+ | ), | ||
+ | </source> | ||
''Was passiert hier?'' | ''Was passiert hier?'' | ||
+ | |||
In diesem Abschnitt legen wir die Grundeinstellungen für unser Modul fest, so z.B. woher die Daten kommen. | In diesem Abschnitt legen wir die Grundeinstellungen für unser Modul fest, so z.B. woher die Daten kommen. | ||
Ergänzt die Datei mit folgendem Code (Video: 17:47): | Ergänzt die Datei mit folgendem Code (Video: 17:47): | ||
− | + | <source lang="php"> | |
− | < | + | // List |
+ | 'list' => array | ||
+ | ( | ||
+ | 'sorting' => array | ||
+ | ( | ||
+ | 'mode' => 2, | ||
+ | 'fields' => array('title'), | ||
+ | 'flag' => 1, | ||
+ | 'panelLayout' => 'filter;sort,search,limit' | ||
+ | ), | ||
+ | </source> | ||
''Was passiert hier?'' | ''Was passiert hier?'' | ||
+ | |||
Im diesem Abschnitt wird festgelegt, wie die Datensätze aufgelistet werden und welche Sortieroptionen dem Nutzer zur Verfügung stehen sollen. | Im diesem Abschnitt wird festgelegt, wie die Datensätze aufgelistet werden und welche Sortieroptionen dem Nutzer zur Verfügung stehen sollen. | ||
− | So steht ' | + | So steht ''panelLayout'' z.B. dafür, welche Optionen in der Kopzeile erscheinen sollen. Semiokolon oder Komma stehen dafür, ob das Layout (ein- oder mehrzeilig). Fragt mich aber nicht, warum ''filter'' in Tristans Beispiel nicht auftaucht. |
− | + | [[Datei:t1_panelLayout.png|Die Elemente des Panel Layouts]] | |
Schaut bzgl. der anderen Optionen der Online-Doku unter "Datensätze auflisten" nach. | Schaut bzgl. der anderen Optionen der Online-Doku unter "Datensätze auflisten" nach. | ||
− | + | *Ergänzt die Datei mit folgendem Code (Video: 20:45): | |
− | < | + | <source lang="php"> |
+ | 'label' => array | ||
+ | ( | ||
+ | 'fields' => array('title'), | ||
+ | 'format' => '%s', | ||
+ | ), | ||
+ | </source> | ||
Was passiert hier? | Was passiert hier? | ||
+ | |||
Hier werden die Bezeichnungen gesetzt, die später in der Listenansicht erscheinen sollen. In unserem Fall also immer der Titel der Screencasts. | Hier werden die Bezeichnungen gesetzt, die später in der Listenansicht erscheinen sollen. In unserem Fall also immer der Titel der Screencasts. | ||
− | |||
− | + | [[Datei:t1_screencastListe.png|Die Titel der Screencasts]] | |
− | < | + | |
+ | *Ergänzt die Datei mit folgendem Code (Video: 21:25): | ||
+ | <source lang="php"> | ||
+ | 'global_operations' => array | ||
+ | ( | ||
+ | 'all' => array | ||
+ | ( | ||
+ | 'label' => &$GLOBALS['TL_LANG']['MSC']['all'], | ||
+ | 'href' => 'act=select', | ||
+ | 'class' => 'header_edit_all', | ||
+ | 'attributes' => 'onclick="Backend.getScrollOffset()" accesskey="e"' | ||
+ | ) | ||
+ | ), | ||
+ | </source> | ||
Was passiert hier? | Was passiert hier? | ||
− | |||
− | + | Bei den 'global operations' handelt es sich um die Bearbeitungsfelder unterhalb der Filterfelder. | |
− | + | [[Datei:t1_globalOperations.png|Die Global Operations]] | |
− | <- | + | |
+ | *Ergänzt die Datei mit folgendem Code (Video: 21:44): | ||
+ | <source lang="php"> | ||
+ | 'operations' => array | ||
+ | ( | ||
+ | 'edit' => array | ||
+ | ( | ||
+ | 'label' => &$GLOBALS['TL_LANG']['tl_screencast']['edit'], | ||
+ | 'href' => 'act=edit', | ||
+ | 'icon' => 'edit.gif' | ||
+ | ), | ||
+ | 'delete' => array | ||
+ | ( | ||
+ | 'label' => &$GLOBALS['TL_LANG']['tl_screencast']['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']['tl_screencast']['show'], | ||
+ | 'href' => 'act=show', | ||
+ | 'icon' => 'show.gif', | ||
+ | 'attributes' => 'style="margin-right:3px"' | ||
+ | ), | ||
+ | ) | ||
+ | ), | ||
+ | </source> | ||
''Was passiert hier?'' | ''Was passiert hier?'' | ||
+ | |||
Bei den 'operations' handelt es sich um die Bearbeitungsfelder zu jedem Listeneintrag. | Bei den 'operations' handelt es sich um die Bearbeitungsfelder zu jedem Listeneintrag. | ||
− | |||
− | + | [[Datei:t1_operations.png|Die Operations]] | |
− | Nun kommen wir zum eigentlichen Herzstück einer jeden Erweiterung: Das Formular | + | Nun kommen wir zum eigentlichen Herzstück einer jeden Erweiterung: Das BE-Formular mit den Eingabefeldern. |
− | 'palettes'. | + | Im DCA wird dies definiert unter dem Bereich ''palettes''. |
− | + | *Ergänzt die Datei mit folgendem Code (Video: 22:55): | |
− | < | + | <source lang="php"> |
+ | // Palettes | ||
+ | 'palettes' => array | ||
+ | ( | ||
+ | 'default' => '{title_legend},type,title,{screencast_legend},url' | ||
+ | ), | ||
+ | </source> | ||
''Was passiert hier?'' | ''Was passiert hier?'' | ||
+ | |||
Die Grobstruktur des Formulars wird angelegt, also das, was später dem BE-User zur Dateneingabe präsentiert wird. Dabei stehen in den geschweifen Klammern immer die Abschnittsnamen. Es folgen die Felder. Ein Semikolon leitet einen neuen Abschnitt ein. | Die Grobstruktur des Formulars wird angelegt, also das, was später dem BE-User zur Dateneingabe präsentiert wird. Dabei stehen in den geschweifen Klammern immer die Abschnittsnamen. Es folgen die Felder. Ein Semikolon leitet einen neuen Abschnitt ein. | ||
− | + | ||
− | + | [[Datei:t1_beModule.png|Das BE Formular des Screencast Moduls]] | |
− | < | + | |
+ | |||
+ | *Ergänzt die Datei mit folgendem Code (Video: 24:30) | ||
+ | <source lang="php"> | ||
+ | // Fields | ||
+ | 'fields' => array | ||
+ | ( | ||
+ | 'id' => array | ||
+ | ( | ||
+ | 'sql' => "int(10) unsigned NOT NULL auto_increment" | ||
+ | ), | ||
+ | 'tstamp' => array | ||
+ | ( | ||
+ | 'sql' => "int(10) unsigned NOT NULL default '0'" | ||
+ | ), | ||
+ | 'title' => array | ||
+ | ( | ||
+ | 'label' => &$GLOBALS['TL_LANG']['tl_screencast']['title'], | ||
+ | 'inputType' => 'text', | ||
+ | 'exclude' => true, | ||
+ | 'sorting' => true, | ||
+ | 'flag' => 1, | ||
+ | 'search' => true, | ||
+ | 'eval' => array( | ||
+ | 'mandatory' => true, | ||
+ | 'unique' => true, | ||
+ | 'maxlength' => 255, | ||
+ | 'tl_class' => 'w50', | ||
+ | |||
+ | ), | ||
+ | 'sql' => "varchar(255) NOT NULL default ''" | ||
+ | ), | ||
+ | 'url' => array | ||
+ | ( | ||
+ | 'label' => &$GLOBALS['TL_LANG']['tl_screencast']['url'], | ||
+ | 'inputType' => 'text', | ||
+ | 'exclude' => true, | ||
+ | 'sql' => "text NULL" | ||
+ | ) | ||
+ | ) | ||
+ | ); | ||
+ | </source> | ||
''Was passiert hier?'' | ''Was passiert hier?'' | ||
− | Im Abschnitt 'fields' werden alle Felder definiert, die in der Datenbank-Tabelle angelegt werden sollen. Dies sind meist mehr Felder, als im Formular des Backend-Moduls ausgegeben werden (z.B. wird man die id wohl fast immer automatisch setzen). Die Felder 'id' und 'tstamp' sind übrigens immer Pflicht. | + | |
− | 'sql' ist (Überraschung) immer das SQL-Statement. | + | Im Abschnitt ''fields'' werden alle Felder definiert, die in der Datenbank-Tabelle angelegt werden sollen. Dies sind meist mehr Felder, als im Formular des Backend-Moduls ausgegeben werden (z.B. wird man die id wohl fast immer automatisch setzen). |
+ | Die Felder ''id'' und ''tstamp'' sind übrigens immer Pflicht. ''sql'' ist (Überraschung) immer das SQL-Statement. | ||
Kümmern wir uns der um die einzelnen Felder: | Kümmern wir uns der um die einzelnen Felder: | ||
'title' und 'url' sind die beiden Eingabefelder im BE-Modul. Diese haben wir auch in den 'palettes' definiert. Beide felder werden noch mit einigen weiteren Eigenschaften konfikuriert: | 'title' und 'url' sind die beiden Eingabefelder im BE-Modul. Diese haben wir auch in den 'palettes' definiert. Beide felder werden noch mit einigen weiteren Eigenschaften konfikuriert: | ||
− | + | *label: Ist eine Referenz auf die Sprachvariable, die noch erstellt wird. | |
− | Ist eine Referenz auf die Sprachvariable, die noch erstellt wird. | + | *inputType: (s. Contao-Docs) in userem Fall ein Textfeld |
− | + | *exclude: Erlaubt dem Admin, dieses Feld später für Redakteure zu sperren. | |
− | (s. Contao-Docs) in userem Fall ein Textfeld | + | *sorting: Bestimmt, dass dieses Feld oben in der Sortierpalette angewählt werden kann |
− | + | *flag: Regelt die Sortierreihenfolge | |
− | Erlaubt dem Admin, dieses Feld später für Redakteure zu sperren. | + | *search: Bestimmt, dass nach dieses Feld oben in der Sortierpalette gesucht werden kann |
− | + | *eval: Konfiguriert ein Eingabefeld im Detail (s. Contao-Docs). In unserem Fall ob es ein Pflichtfeld ist, ob es einzigartig ist, die Textfeldlänge sowie die Darstellung, wie dieses Feld im BE-Modul angezeigt wird. Schaut euch zu ''tl_class'' auch das Video an oder den Abschnitt ''Felder ausrichten'' in den Docs. | |
− | Bestimmt, dass dieses Feld oben in der Sortierpalette angewählt werden kann | + | |
− | + | ||
− | Regelt die Sortierreihenfolge | + | |
− | + | ||
− | Bestimmt, dass nach dieses Feld oben in der Sortierpalette gesucht werden kann | + | |
− | + | ||
− | Konfiguriert ein Eingabefeld im Detail (s. Contao-Docs). In unserem Fall ob es ein Pflichtfeld ist, ob es einzigartig ist, die Textfeldlänge sowie die Darstellung, wie dieses Feld im BE-Modul angezeigt wird. Schaut euch zu tl_class auch das Video an oder den Abschnitt | + | |
− | + | *Diejenigen, die den Code aus der ''tl_theme.php'' kopiert haben: | |
Löscht bitte den nachfolgenden Code aus eurer Datei. Die Klassendefinition wird für diese Beispiel nicht benötigt. | Löscht bitte den nachfolgenden Code aus eurer Datei. Die Klassendefinition wird für diese Beispiel nicht benötigt. | ||
− | + | *Der große Moment ist nah: Navigiert im Contao-BE zu ''System->Erweiterungsverwaltung'' und klickt auf Datenbank aktualisieren. | |
Wenn ihr alles richtig gemacht habt, solltet ihr nun eine Meldung von Contao darüber erhalten, dass eine neue Tabelle angelegt wird. Klickt auf Aktualisieren. | Wenn ihr alles richtig gemacht habt, solltet ihr nun eine Meldung von Contao darüber erhalten, dass eine neue Tabelle angelegt wird. Klickt auf Aktualisieren. | ||
− | + | *Jetzt könntet ihr eigentlich schon einen Screencast anlegen....aber es fehlen noch die Sprachvariablen. | |
− | + | *Erstellt daher eine Datei ''tl_screencast.php'' im Verzeichnis ''screencast/languages/de''. | |
− | + | *Gebt folgenden Code in diese Datei ein (Video: 32:30): | |
− | < | + | <source lang="php"> |
+ | <?php | ||
+ | |||
+ | $GLOBALS['TL_LANG']['tl_screencast']['title_legend'] = 'Titel'; | ||
+ | |||
+ | $GLOBALS['TL_LANG']['tl_screencast']['type'][0] = 'Typ'; | ||
+ | $GLOBALS['TL_LANG']['tl_screencast']['type'][1] = 'Wählen Sie hier aus, ob es sich um ein externes oder lokales Video handelt.'; | ||
+ | |||
+ | $GLOBALS['TL_LANG']['tl_screencast']['title'][0] = 'Titel'; | ||
+ | $GLOBALS['TL_LANG']['tl_screencast']['title'][1] = 'Geben Sie hier den Screencast Titel ein.'; | ||
+ | |||
+ | $GLOBALS['TL_LANG']['tl_screencast']['screencast_legend'] = 'Screencast'; | ||
+ | |||
+ | $GLOBALS['TL_LANG']['tl_screencast']['url'][0] = 'Video URL'; | ||
+ | $GLOBALS['TL_LANG']['tl_screencast']['url'][1] = 'Geben Sie hier die Video URL ein.'; | ||
+ | |||
+ | $GLOBALS['TL_LANG']['tl_screencast']['new'][0] = 'Neuer Screencast'; | ||
+ | $GLOBALS['TL_LANG']['tl_screencast']['new'][1] = 'Einen neuen Screencast anlegen'; | ||
+ | |||
+ | $GLOBALS['TL_LANG']['tl_screencast']['edit'][0] = 'Screencast bearbeiten'; | ||
+ | $GLOBALS['TL_LANG']['tl_screencast']['edit'][1] = 'Screencast ID %s bearbeiten'; | ||
+ | |||
+ | $GLOBALS['TL_LANG']['tl_screencast']['delete'][0] = 'Screencast löschen'; | ||
+ | $GLOBALS['TL_LANG']['tl_screencast']['delete'][1] = 'Screencast ID %s löschen'; | ||
+ | |||
+ | $GLOBALS['TL_LANG']['tl_screencast']['show'][0] = 'Screencastdetails'; | ||
+ | $GLOBALS['TL_LANG']['tl_screencast']['show'][1] = 'Details des Screencast ID %s anzeigen'; | ||
+ | |||
+ | |||
+ | </source> | ||
''Was passiert hier?'' | ''Was passiert hier?'' | ||
+ | |||
Es werden alle Übersetzungen angelegt, die für das Backend notwendig sind. | Es werden alle Übersetzungen angelegt, die für das Backend notwendig sind. | ||
− | Die notwendigen Keys der Arrays findet ihr z.T. in der DCA-Datei unter 'paletts' bzw. im Bereich 'global operations' und 'operations'. Die Beschreibungen der Felder liegen immer auf dem zweiten Arrayeintrag. | + | Die notwendigen Keys der Arrays findet ihr z.T. in der DCA-Datei unter ''paletts'' bzw. im Bereich ''global operations'' und ''operations''. Die Beschreibungen der Felder liegen immer auf dem zweiten Arrayeintrag. |
− | Beispiel: | + | |
− | ['title'] bezieht sich auf das den paletts-Eintrag title. [0] ist dabei der Titel des BE-Feldes.[1] ist die Beschreibung unterhalb des Feldes. Diese wird automatisch hinzugefügt. | + | ''Beispiel:'' |
+ | |||
+ | ''['title']'' bezieht sich auf das den paletts-Eintrag title. ''[0]'' ist dabei der Titel des BE-Feldes.''[1]'' ist die Beschreibung unterhalb des Feldes. Diese wird automatisch hinzugefügt. | ||
+ | |||
+ | [[Datei:t1_title.png|Die Übersetzungen zu den Feldern]] | ||
− | |||
=Anlegen der Klasse für die Ausgabe-Logik= | =Anlegen der Klasse für die Ausgabe-Logik= | ||
(Video:39:00) | (Video:39:00) | ||
+ | *Legt im Verzeichnis ''screencast/modules/'' die Datei ''ModuleScreencastList.php'' | ||
+ | *Legt im Verzeichnis ''screencast/templates'' die Datei ''mod_screencast_list.html5'' an. Wer noch mit xhtml arbeitet: Legt auch noch eine ''mod_screencast_list.xhtm''l an. Ich gehe im Folgenden aber nur auf die .html5 Datei ein. | ||
+ | *Fügt dort folgenden Code in die Datei ''ModuleScreencastList.php'' ein: | ||
+ | <source lang=php"> | ||
+ | <?php | ||
+ | |||
+ | class ModuleScreencastList extends Module | ||
+ | { | ||
+ | /** | ||
+ | * Template | ||
+ | * @var string | ||
+ | */ | ||
+ | protected $strTemplate = 'mod_screencast_list'; | ||
+ | |||
+ | /** | ||
+ | * Compile the current element | ||
+ | */ | ||
+ | protected function compile() | ||
+ | { | ||
+ | /** @var \Contao\Database\Result $rs */ | ||
+ | $rs = Database::getInstance() | ||
+ | ->query('SELECT * FROM tl_screencast ORDER BY title'); | ||
+ | |||
+ | $this->Template->screencasts = $rs->fetchAllAssoc(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </source> | ||
+ | |||
+ | |||
+ | ''Was passiert hier?'' | ||
+ | In dieser Datei werden die Datensätze aus der Datenbank gelesen und an das FE-Template übergeben. | ||
+ | Die hierzu notwendige Klasse muss den selben Namen erhalten, wie der Dateiname. Ferner muss die Klasse von der übergeordneten Klasse ''Module'' erben. | ||
+ | |||
+ | Die folgenden Anweisungen kann man eigentlich nur richtig verstehen, wenn man sich die Datei module.php in system/modules/core/modules anschaut, bzw. einen Blick in die weiter übergeordnetetn Klassen wirft. | ||
+ | |||
+ | Ich versuch's mal ohne Referenz auf die übergeordneten Klassen: | ||
+ | #Zunächst wird Contao die Template-Datei übergeben ($strTemplate). | ||
+ | #Anschließend folgt die Methode compile(), welche für die Daten für die Übergabe an das Template vorbereitet. | ||
+ | #Nun wird über die statische Methode getInstance() ein Contao-Datenbankobjekt erzeugt (system/modules/core/library/Contao/Database.php). Dieses Objekt hat die Methoden query und liefert ein Contao-DB-Ergebnisobjekt zurück (system/modules/core/library/Contao/Database/Result.php). Dieses Objekt wiederum hat die Methode fetchAllAssoc(), welche ein assoziatives Array zurückgibt (Key=Feldnamen). Diese speichern wir in der Variablen screencasts, welche durch die übergeordneten Klassen von ModuleScreencastList einem FE-Templateobjekt zugeordnet wird. | ||
+ | |||
=Das FE-Template erstellen= | =Das FE-Template erstellen= | ||
(Video 43:00) | (Video 43:00) | ||
− | = | + | |
+ | Wer faul ist, kopiert sich den Code aus der ''mod_flash.html5'' (system/modules/core/templates) in seine Datei ''mod_screencast_list.html5''. | ||
+ | |||
+ | Am Ende sollte der Code wie folgt aussehen: | ||
+ | |||
+ | <source lang="php"> | ||
+ | |||
+ | <div class="<?php echo $this->class; ?> block"<?php echo $this->cssID; ?><?php if ($this->style): ?> style="<?php echo $this->style; ?>"<?php endif; ?>> | ||
+ | <?php if ($this->headline): ?> | ||
+ | |||
+ | <<?php echo $this->hl; ?>><?php echo $this->headline; ?></<?php echo $this->hl; ?>> | ||
+ | <?php endif; ?> | ||
+ | |||
+ | <?php foreach ($this->screencasts as $screencast): ?> | ||
+ | <h2><?php echo $screencast['title']; ?></h2> | ||
+ | <p> | ||
+ | <iframe width="560" height="315" src="http://www.youtube-nocookie.com/embed/<?php echo str_replace('http://youtu.be/', '', $screencast['url']); ?>?rel=0" frameborder="0" allowfullscreen></iframe> | ||
+ | </p> | ||
+ | <?php endforeach; ?> | ||
+ | |||
+ | </div> | ||
+ | |||
+ | </source> | ||
+ | |||
+ | ''Was passiert hier?'' | ||
+ | |||
+ | Das Template wird im Kontext der FE-Templateklasse ausgegeben. Daher kann mit ''$this'' auf die Attribute und Methoden des Objekts zugegriffen werden. Dies haben wir in der compile()-Methode in ''ModuleScreencastList.php'' definiert. | ||
+ | |||
+ | =Das FE-Template im System registrieren (Video 44:00)= | ||
(Video 43:00) | (Video 43:00) | ||
+ | Ergänzt die Datei config.php um folgenden Code | ||
+ | |||
+ | <source lang="php"> | ||
+ | /** | ||
+ | * Front end modules | ||
+ | */ | ||
+ | $GLOBALS['FE_MOD']['screencast'] = array | ||
+ | ( | ||
+ | 'screencast_list' => 'ModuleScreencastList', | ||
+ | ); | ||
+ | |||
+ | </source> | ||
+ | |||
+ | ''Was passiert hier?'' | ||
+ | Unser FE-Template muss noch dem Contao-System bekannt gemacht werden. Jetzt sollte man das Modul bereits im Backend in der Modulliste auswählen können. Es fehlt jedoch noch die Übersetzung. | ||
+ | |||
+ | =Die Übersetzung für das FE-Template erstellen (Video 44:00)= | ||
+ | Öffnet die Datei modules.php in screencast/languages/de/ und ergänzt folgende Zeilen Code: | ||
+ | |||
+ | <source lang="php"> | ||
+ | |||
+ | $GLOBALS['TL_LANG']['FMD']['screencast_list'][0] = 'Screencast Liste'; | ||
+ | $GLOBALS['TL_LANG']['FMD']['screencast_list'][1] = 'Auflistung der Screencasts'; | ||
+ | |||
+ | </source> | ||
+ | |||
+ | ''Was passiert hier?'' | ||
+ | Nun....in der Modulliste steht künftig "Screencast Liste". | ||
+ | |||
=Erstellung der autoloader-Dateien= | =Erstellung der autoloader-Dateien= | ||
+ | Der Autoloader sorgt z.B. dafür, dass alle notwendigen Templates bzw. Klassen des Moduls im Contao-System registriert werden. Praktischerweise können die autoloader-Dateien automatisch generiert werden. | ||
+ | Navigiert hierzu im Backend auf ''Entwickler-Tools->Autoload-Creator''. | ||
+ | Wählt das Modul screencast aus und klickt auf ''Autoload-Dateien erstellen''. | ||
+ | Prüft, ob die Dateien ''autoload.php'' und autiload.ini in eurem ''config''-Verzeichnis erstellt wurden. | ||
+ | autoload.php: | ||
+ | |||
+ | <source lang="php"> | ||
+ | <?php | ||
+ | |||
+ | /** | ||
+ | * Contao Open Source CMS | ||
+ | * | ||
+ | * Copyright (C) 2005-2013 Leo Feyer | ||
+ | * | ||
+ | * @package Screencast | ||
+ | * @link https://contao.org | ||
+ | * @license http://www.gnu.org/licenses/lgpl-3.0.html LGPL | ||
+ | */ | ||
+ | |||
+ | |||
+ | /** | ||
+ | * Register the classes | ||
+ | */ | ||
+ | ClassLoader::addClasses(array | ||
+ | ( | ||
+ | // Modules | ||
+ | 'ModuleScreencastList' => 'system/modules/screencast/modules/ModuleScreencastList.php', | ||
+ | )); | ||
+ | |||
+ | |||
+ | /** | ||
+ | * Register the templates | ||
+ | */ | ||
+ | TemplateLoader::addFiles(array | ||
+ | ( | ||
+ | 'mod_screencast_list' => 'system/modules/screencast/templates', | ||
+ | )); | ||
+ | |||
+ | </source> | ||
+ | |||
+ | autoload.ini | ||
+ | <source lang="php"> | ||
+ | |||
+ | ;; | ||
+ | ; Configure what you want the autoload creator to register | ||
+ | ;; | ||
+ | register_namespaces = true | ||
+ | register_classes = true | ||
+ | register_templates = true | ||
+ | |||
+ | </source> | ||
+ | |||
=Geschafft!= | =Geschafft!= | ||
+ | Wenn ich mich nicht verschrieben habe und ihr alles richtig gemacht habt, könnt ihr eure Screencast-Modul nun einsetzen. | ||
+ | |||
=Ausblick= | =Ausblick= | ||
+ | Im folgenden Teil wird unser Modul erweitert. Dabei geht es schwerpunktsmässig um das Hinzufügen von sog. Subpaletten, die eine kontextsensitive (schönes Wort) Auswahl von Einstellungen im Modulbereich erlauben. Zu Deutsch: Wenn der Nutzer die Wahl zwischen verschiedenen Screencast-Quellen (z.B. Youtube, Vimeo etc.) hat, verändern sich die folgenden Eingabe-/Auswahlfelder. | ||
+ | |||
+ | Das Video könnt ihr euch hier schon ansehen: | ||
+ | Videolink : [http://www.youtube.com/watch?v=I1-1mqIR_B4&list=PL3mn8AtCRAstvuAWY8dhrHisMYapPxOnt&index=4 DCA Paletten und Subpaletten, MetaPalettes] | ||
+ | |||
+ | So...ich habe erstmal fertig. Bis demnächst. | ||
+ | Grüße von | ||
+ | kobajashi | ||
+ | |||
=Weiterführende Links= | =Weiterführende Links= | ||
+ | [[C3: Tutorial Extension Entwicklung 2.Teil: Selective DCA Paletten und Subpaletten|2. Teil Selective DCA Paletten und Subpaletten]] |
Aktuelle Version vom 2. Oktober 2015, 16:13 Uhr
Inhaltsverzeichnis
- 1 Einleitung
- 2 Einen Menüeintrag im Inhaltsbereich der Backend-Module erzeugen.
- 3 Das Formular zur Eintragung der Daten erstellen, sowie die Datenbank-Tabelle anlegen.
- 4 Anlegen der Klasse für die Ausgabe-Logik
- 5 Das FE-Template erstellen
- 6 Das FE-Template im System registrieren (Video 44:00)
- 7 Die Übersetzung für das FE-Template erstellen (Video 44:00)
- 8 Erstellung der autoloader-Dateien
- 9 Geschafft!
- 10 Ausblick
- 11 Weiterführende Links
Einleitung
Seit 2010 arbeite ich nun schon mit Contao. Vorher habe ich die CMS Joomla, Typo3 und Drupal ausprobiert und muss sagen: Contao rocks! Leider hat das CMS aus meiner Sicht jedoch einen entscheidenden Nachteil gegenüber anderen Systemen: Es gibt nur wenige Tutorials, die "semiprofessionellen" Programmierern einen schrittweisen und zusammenhängenden Einstieg in die Extension-Entwicklung mit Contao 3 anhand eines Praxisbeispiels ermöglichen.
Die Screencast-Reihe von Tristan Lins auf Youtube stellt dabei eine Ausnahme dar. Ich persönlich mag es aber, Tutorials auch in geschriebener Form vor mir zu haben. Daher habe ich damit begonnen, die Videos in dieses Wiki zu übertragen. Viel Spaß damit!
Videolink: Basics - der Contao Aufbau, DCA
An wen richtet sich dieses Tutorial?
Dieses Tutorial ist für all diejenigen gedacht, die ein Step-by-Step Tutorial zum Einstieg in die Extension-Entwicklung mit Contao 3 suchen.
Lernziel
In diesem Tutorial lernt ihr die Grundlagen der Extension-Entwicklung mit Contao 3 anhand eines praktischen Beispiels. Es wird ein Modul programmiert, welches verschiedene Screencast-URLs inkl. Titel auflistet.
So sieht das fertige Modul aus:
Was man wissen sollte
Grundlagen in PHP, objektorientierter Programmierung und SQL sind nötig. Natürlich sollte man sich auch mit den Grundlagen von Contao 3 auskennen.
Vorbereitung
Eine Version von Contao 3.0.4 oder höher sollte installiert sein. Optional: Da die Extension in das bestehende „Music Academy“-Theme integriert wird, empfiehlt es sich, selbiges zu installieren. Ferner sollte folgende Ordnerstruktur in contao/system/modules angelegt werden:
Zum Verständnis: Im Verzeichnis modules liegen die Module, die bereits von Contao mitgeliefert werden, wie z.B. FAQ, Calendar etc. Auch unser Erweiterungsmodul 'screencast' gehört in dieses Verzeichnis.
Source-Code
Den Quellcode könnt ihr hier: https://github.com/bit3/contao-screencast3 herunterladen.
Einen Menüeintrag im Inhaltsbereich der Backend-Module erzeugen.
- Erstellt im Verzeichnis config die Datei config.php.
In der config.php werden z.B. Frontend- und Backend-Module registriert. - Schreibt in die config.php folgenden Code:
<?php /** * Back end modules */ $GLOBALS['BE_MOD']['content']['screencast'] = array( 'tables' => array('tl_screencast'), 'icon' => 'system/modules/screencast/assets/images/screencast.png' );
Dabei steht ['BE_MOD']['content'] für die Elemente der Backend-Module im Inhaltsbereich (Array). Durch die Erweiterung des Arrays um ['screencast'] wird unser neues Modul referenziert. Als Wert wird dem Array ein assoziatives Array mit zwei Einträgen (Verweis auf die Tabelle in der Datenbank, sowie auf die Bilddatei) übergeben.
- Fügt in den Ordner screencast/assets/images ein Icon für euer Modul ein.
- Da das assets-Verzeichnis geschützt ist, müsst ihr noch eine .htaccess Datei in screencast/assets/ speichern. Darin muss stehen:
<IfModule !mod_authz_core.c> Order allow,deny Allow from all </IfModule> <IfModule mod_authz_core.c> Require all granted </IfModule>
Achtung: Hier besteht eine Abweichung vom Screencast, da ab Apache-Version 2.4 die Anweisung anders lauten muss.
Nun soll in der Auflistung der Elemente im Backend-Modul auch eine entsprechende Übersetzung ausgegeben werden.
- Erstellt hierzu ein Verzeichnis de in eurem Verzeichnis screencast/languages/
- Erstellt in diesem Verzeichnis eine Datei modules.php
- In diese Datei gebt ihr folgenden Code ein:
<?php $GLOBALS['TL_LANG']['MOD']['screencast'][0] = 'Screencasts'; $GLOBALS['TL_LANG']['MOD']['screencast'][1] = 'Screencasts verwalten';
- Öffnet eure Contao-Backend und navigiert dort zu System->Einstellungen
- Setzt dort einen Haken unter den Sicherheitseinstellungen->Internen Cache (ab v 3.1. Globale Einstellungen->Internen Cache umgehen) umgehen. Und
Sicherheitseinstellungen->Fehlermeldungen anzeigen. - Eure Seitenleiste sollte nach einer Aktualisierung der Seite nun so aussehen:
Heureka! Der Eintrag erscheint in der Liste. Leider wirft Contao jedoch nach Klick auf Screencast noch eine Fehlermeldung.
Was fehlt? Contao kann noch kein DCA-Objekt erstellen.
Was macht ein DCA?
"Data Container Arrays (DCAs) dienen zur Speicherung von Tabellen-Metadaten. Jedes DCA beschreibt die Konfiguration einer bestimmten Tabelle, ihre Beziehungen zu anderen Tabellen sowie die einzelnen Felder. Die Contao Core-Engine erkennt anhand dieser Metadaten, wie Datensätze aufgelistet, bearbeitet und gespeichert werden."
(Quelle: https://contao.org/de/manual/3.0/data-container-arrays.html, Stand: 6.4.13)
Achtung: Momentan gibt es in Abhängigkeit der Version mehrere DCA-Dokus. Schaut daher bitte vorher, welche Doku für eure Contao Version zutrifft. |
Wie ist ein DCA aufgebaut?
"Ein Data Container Array ist in 6 Sektionen unterteilt. Die erste Sektion speichert globale Informationen wie z.B. Relationen zu anderen Tabellen. Die zweite und dritte Sektion legt fest, wie Datensätze aufgelistet werden und welche Aktionen ein Benutzer ausführen kann. Die vierte Sektion definiert verschiedene Gruppen von Eingabefelder (Paletten) und die letzten beiden Sektionen beschreiben die Eingabefelder im Detail."
(Quelle: https://contao.org/de/manual/3.0/data-container-arrays.html, Stand: 6.4.13)
Neu in Contao 3: In der DCA-Datei werden auch die SQL-Befehle eingetragen. Eine separate Datei ist nicht mehr notwendig.
Alles klar? Nicht? Ok...dann Schritt für Schritt.
Das Formular zur Eintragung der Daten erstellen, sowie die Datenbank-Tabelle anlegen.
Erstellt im Verzeichnis screencast/dca/ eine Datei mit Namen tl_screencast.php.
Die Tabellenkonfiguartion
Anmerkung: Ab jetzt ist "Mut zur Lücke" gefordert. Einige Sachverhalte sind mir in dem Screencast nicht ganz klar geworden. Leider ist auch die Dokumentation auf Contao.org in diesem Bereich noch recht rudimentär. Ich schreib daher auf, was ich verstanden habe.
Auf der Contao-Seite kann man sich über die möglichen Einträge in den DCA informieren. https://contao.org/de/manual/3.0/data-container-arrays.html
Leider ist hier derzeit noch nicht aufgeführt, welchem Array-Abschnitt welche Einträge zugeordnet sind. Tristan empfiehlt, sich die Verwendungsmöglichkeiten in bestehenden Modulen abzugucken. Für die nachfolgenden Erklärungen empfiehlt es sich jedoch trotzdem, den DCA-Teil der Online-Doku aufzufrufen, um scih über die Bedeutung der Arrayeinträge zu informieren.
Wer nicht alles selber schreiben möchte, kopiert sich nun erstmal den gesamten Inhalt der Datei sytem/modules/core/dca/tl_theme.php in die tl_screencast.php und modifiziert diese nur entsprechend der folgenden Beispiele.
- Schreibt in die Datei tl_screencast.php folgende Zeilen Code:
<?php /** * Table tl_screencast */ $GLOBALS['TL_DCA']['tl_screencast'] = array ( // Config 'config' => array ( 'dataContainer' => 'Table', 'enableVersioning' => true, 'sql' => array ( 'keys' => array ( 'id' => 'primary' ) ), ),
Was passiert hier?
In diesem Abschnitt legen wir die Grundeinstellungen für unser Modul fest, so z.B. woher die Daten kommen. Ergänzt die Datei mit folgendem Code (Video: 17:47):
// List 'list' => array ( 'sorting' => array ( 'mode' => 2, 'fields' => array('title'), 'flag' => 1, 'panelLayout' => 'filter;sort,search,limit' ),
Was passiert hier?
Im diesem Abschnitt wird festgelegt, wie die Datensätze aufgelistet werden und welche Sortieroptionen dem Nutzer zur Verfügung stehen sollen. So steht panelLayout z.B. dafür, welche Optionen in der Kopzeile erscheinen sollen. Semiokolon oder Komma stehen dafür, ob das Layout (ein- oder mehrzeilig). Fragt mich aber nicht, warum filter in Tristans Beispiel nicht auftaucht.
Schaut bzgl. der anderen Optionen der Online-Doku unter "Datensätze auflisten" nach.
- Ergänzt die Datei mit folgendem Code (Video: 20:45):
'label' => array ( 'fields' => array('title'), 'format' => '%s', ),
Was passiert hier?
Hier werden die Bezeichnungen gesetzt, die später in der Listenansicht erscheinen sollen. In unserem Fall also immer der Titel der Screencasts.
- Ergänzt die Datei mit folgendem Code (Video: 21:25):
'global_operations' => array ( 'all' => array ( 'label' => &$GLOBALS['TL_LANG']['MSC']['all'], 'href' => 'act=select', 'class' => 'header_edit_all', 'attributes' => 'onclick="Backend.getScrollOffset()" accesskey="e"' ) ),
Was passiert hier?
Bei den 'global operations' handelt es sich um die Bearbeitungsfelder unterhalb der Filterfelder.
- Ergänzt die Datei mit folgendem Code (Video: 21:44):
'operations' => array ( 'edit' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_screencast']['edit'], 'href' => 'act=edit', 'icon' => 'edit.gif' ), 'delete' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_screencast']['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']['tl_screencast']['show'], 'href' => 'act=show', 'icon' => 'show.gif', 'attributes' => 'style="margin-right:3px"' ), ) ),
Was passiert hier?
Bei den 'operations' handelt es sich um die Bearbeitungsfelder zu jedem Listeneintrag.
Nun kommen wir zum eigentlichen Herzstück einer jeden Erweiterung: Das BE-Formular mit den Eingabefeldern. Im DCA wird dies definiert unter dem Bereich palettes.
- Ergänzt die Datei mit folgendem Code (Video: 22:55):
// Palettes 'palettes' => array ( 'default' => '{title_legend},type,title,{screencast_legend},url' ),
Was passiert hier?
Die Grobstruktur des Formulars wird angelegt, also das, was später dem BE-User zur Dateneingabe präsentiert wird. Dabei stehen in den geschweifen Klammern immer die Abschnittsnamen. Es folgen die Felder. Ein Semikolon leitet einen neuen Abschnitt ein.
- Ergänzt die Datei mit folgendem Code (Video: 24:30)
// Fields 'fields' => array ( 'id' => array ( 'sql' => "int(10) unsigned NOT NULL auto_increment" ), 'tstamp' => array ( 'sql' => "int(10) unsigned NOT NULL default '0'" ), 'title' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_screencast']['title'], 'inputType' => 'text', 'exclude' => true, 'sorting' => true, 'flag' => 1, 'search' => true, 'eval' => array( 'mandatory' => true, 'unique' => true, 'maxlength' => 255, 'tl_class' => 'w50', ), 'sql' => "varchar(255) NOT NULL default ''" ), 'url' => array ( 'label' => &$GLOBALS['TL_LANG']['tl_screencast']['url'], 'inputType' => 'text', 'exclude' => true, 'sql' => "text NULL" ) ) );
Was passiert hier?
Im Abschnitt fields werden alle Felder definiert, die in der Datenbank-Tabelle angelegt werden sollen. Dies sind meist mehr Felder, als im Formular des Backend-Moduls ausgegeben werden (z.B. wird man die id wohl fast immer automatisch setzen). Die Felder id und tstamp sind übrigens immer Pflicht. sql ist (Überraschung) immer das SQL-Statement.
Kümmern wir uns der um die einzelnen Felder: 'title' und 'url' sind die beiden Eingabefelder im BE-Modul. Diese haben wir auch in den 'palettes' definiert. Beide felder werden noch mit einigen weiteren Eigenschaften konfikuriert:
- label: Ist eine Referenz auf die Sprachvariable, die noch erstellt wird.
- inputType: (s. Contao-Docs) in userem Fall ein Textfeld
- exclude: Erlaubt dem Admin, dieses Feld später für Redakteure zu sperren.
- sorting: Bestimmt, dass dieses Feld oben in der Sortierpalette angewählt werden kann
- flag: Regelt die Sortierreihenfolge
- search: Bestimmt, dass nach dieses Feld oben in der Sortierpalette gesucht werden kann
- eval: Konfiguriert ein Eingabefeld im Detail (s. Contao-Docs). In unserem Fall ob es ein Pflichtfeld ist, ob es einzigartig ist, die Textfeldlänge sowie die Darstellung, wie dieses Feld im BE-Modul angezeigt wird. Schaut euch zu tl_class auch das Video an oder den Abschnitt Felder ausrichten in den Docs.
- Diejenigen, die den Code aus der tl_theme.php kopiert haben:
Löscht bitte den nachfolgenden Code aus eurer Datei. Die Klassendefinition wird für diese Beispiel nicht benötigt.
- Der große Moment ist nah: Navigiert im Contao-BE zu System->Erweiterungsverwaltung und klickt auf Datenbank aktualisieren.
Wenn ihr alles richtig gemacht habt, solltet ihr nun eine Meldung von Contao darüber erhalten, dass eine neue Tabelle angelegt wird. Klickt auf Aktualisieren.
- Jetzt könntet ihr eigentlich schon einen Screencast anlegen....aber es fehlen noch die Sprachvariablen.
- Erstellt daher eine Datei tl_screencast.php im Verzeichnis screencast/languages/de.
- Gebt folgenden Code in diese Datei ein (Video: 32:30):
<?php $GLOBALS['TL_LANG']['tl_screencast']['title_legend'] = 'Titel'; $GLOBALS['TL_LANG']['tl_screencast']['type'][0] = 'Typ'; $GLOBALS['TL_LANG']['tl_screencast']['type'][1] = 'Wählen Sie hier aus, ob es sich um ein externes oder lokales Video handelt.'; $GLOBALS['TL_LANG']['tl_screencast']['title'][0] = 'Titel'; $GLOBALS['TL_LANG']['tl_screencast']['title'][1] = 'Geben Sie hier den Screencast Titel ein.'; $GLOBALS['TL_LANG']['tl_screencast']['screencast_legend'] = 'Screencast'; $GLOBALS['TL_LANG']['tl_screencast']['url'][0] = 'Video URL'; $GLOBALS['TL_LANG']['tl_screencast']['url'][1] = 'Geben Sie hier die Video URL ein.'; $GLOBALS['TL_LANG']['tl_screencast']['new'][0] = 'Neuer Screencast'; $GLOBALS['TL_LANG']['tl_screencast']['new'][1] = 'Einen neuen Screencast anlegen'; $GLOBALS['TL_LANG']['tl_screencast']['edit'][0] = 'Screencast bearbeiten'; $GLOBALS['TL_LANG']['tl_screencast']['edit'][1] = 'Screencast ID %s bearbeiten'; $GLOBALS['TL_LANG']['tl_screencast']['delete'][0] = 'Screencast löschen'; $GLOBALS['TL_LANG']['tl_screencast']['delete'][1] = 'Screencast ID %s löschen'; $GLOBALS['TL_LANG']['tl_screencast']['show'][0] = 'Screencastdetails'; $GLOBALS['TL_LANG']['tl_screencast']['show'][1] = 'Details des Screencast ID %s anzeigen';
Was passiert hier?
Es werden alle Übersetzungen angelegt, die für das Backend notwendig sind. Die notwendigen Keys der Arrays findet ihr z.T. in der DCA-Datei unter paletts bzw. im Bereich global operations und operations. Die Beschreibungen der Felder liegen immer auf dem zweiten Arrayeintrag.
Beispiel:
['title'] bezieht sich auf das den paletts-Eintrag title. [0] ist dabei der Titel des BE-Feldes.[1] ist die Beschreibung unterhalb des Feldes. Diese wird automatisch hinzugefügt.
Anlegen der Klasse für die Ausgabe-Logik
(Video:39:00)
- Legt im Verzeichnis screencast/modules/ die Datei ModuleScreencastList.php
- Legt im Verzeichnis screencast/templates die Datei mod_screencast_list.html5 an. Wer noch mit xhtml arbeitet: Legt auch noch eine mod_screencast_list.xhtml an. Ich gehe im Folgenden aber nur auf die .html5 Datei ein.
- Fügt dort folgenden Code in die Datei ModuleScreencastList.php ein:
<?php class ModuleScreencastList extends Module { /** * Template * @var string */ protected $strTemplate = 'mod_screencast_list'; /** * Compile the current element */ protected function compile() { /** @var \Contao\Database\Result $rs */ $rs = Database::getInstance() ->query('SELECT * FROM tl_screencast ORDER BY title'); $this->Template->screencasts = $rs->fetchAllAssoc(); } }
Was passiert hier?
In dieser Datei werden die Datensätze aus der Datenbank gelesen und an das FE-Template übergeben.
Die hierzu notwendige Klasse muss den selben Namen erhalten, wie der Dateiname. Ferner muss die Klasse von der übergeordneten Klasse Module erben.
Die folgenden Anweisungen kann man eigentlich nur richtig verstehen, wenn man sich die Datei module.php in system/modules/core/modules anschaut, bzw. einen Blick in die weiter übergeordnetetn Klassen wirft.
Ich versuch's mal ohne Referenz auf die übergeordneten Klassen:
- Zunächst wird Contao die Template-Datei übergeben ($strTemplate).
- Anschließend folgt die Methode compile(), welche für die Daten für die Übergabe an das Template vorbereitet.
- Nun wird über die statische Methode getInstance() ein Contao-Datenbankobjekt erzeugt (system/modules/core/library/Contao/Database.php). Dieses Objekt hat die Methoden query und liefert ein Contao-DB-Ergebnisobjekt zurück (system/modules/core/library/Contao/Database/Result.php). Dieses Objekt wiederum hat die Methode fetchAllAssoc(), welche ein assoziatives Array zurückgibt (Key=Feldnamen). Diese speichern wir in der Variablen screencasts, welche durch die übergeordneten Klassen von ModuleScreencastList einem FE-Templateobjekt zugeordnet wird.
Das FE-Template erstellen
(Video 43:00)
Wer faul ist, kopiert sich den Code aus der mod_flash.html5 (system/modules/core/templates) in seine Datei mod_screencast_list.html5.
Am Ende sollte der Code wie folgt aussehen:
<div class="<?php echo $this->class; ?> block"<?php echo $this->cssID; ?><?php if ($this->style): ?> style="<?php echo $this->style; ?>"<?php endif; ?>> <?php if ($this->headline): ?> <<?php echo $this->hl; ?>><?php echo $this->headline; ?></<?php echo $this->hl; ?>> <?php endif; ?> <?php foreach ($this->screencasts as $screencast): ?> <h2><?php echo $screencast['title']; ?></h2> <p> <iframe width="560" height="315" src="http://www.youtube-nocookie.com/embed/<?php echo str_replace('http://youtu.be/', '', $screencast['url']); ?>?rel=0" frameborder="0" allowfullscreen></iframe> </p> <?php endforeach; ?> </div>
Was passiert hier?
Das Template wird im Kontext der FE-Templateklasse ausgegeben. Daher kann mit $this auf die Attribute und Methoden des Objekts zugegriffen werden. Dies haben wir in der compile()-Methode in ModuleScreencastList.php definiert.
Das FE-Template im System registrieren (Video 44:00)
(Video 43:00) Ergänzt die Datei config.php um folgenden Code
/** * Front end modules */ $GLOBALS['FE_MOD']['screencast'] = array ( 'screencast_list' => 'ModuleScreencastList', );
Was passiert hier? Unser FE-Template muss noch dem Contao-System bekannt gemacht werden. Jetzt sollte man das Modul bereits im Backend in der Modulliste auswählen können. Es fehlt jedoch noch die Übersetzung.
Die Übersetzung für das FE-Template erstellen (Video 44:00)
Öffnet die Datei modules.php in screencast/languages/de/ und ergänzt folgende Zeilen Code:
$GLOBALS['TL_LANG']['FMD']['screencast_list'][0] = 'Screencast Liste'; $GLOBALS['TL_LANG']['FMD']['screencast_list'][1] = 'Auflistung der Screencasts';
Was passiert hier? Nun....in der Modulliste steht künftig "Screencast Liste".
Erstellung der autoloader-Dateien
Der Autoloader sorgt z.B. dafür, dass alle notwendigen Templates bzw. Klassen des Moduls im Contao-System registriert werden. Praktischerweise können die autoloader-Dateien automatisch generiert werden. Navigiert hierzu im Backend auf Entwickler-Tools->Autoload-Creator. Wählt das Modul screencast aus und klickt auf Autoload-Dateien erstellen. Prüft, ob die Dateien autoload.php und autiload.ini in eurem config-Verzeichnis erstellt wurden. autoload.php:
<?php /** * Contao Open Source CMS * * Copyright (C) 2005-2013 Leo Feyer * * @package Screencast * @link https://contao.org * @license http://www.gnu.org/licenses/lgpl-3.0.html LGPL */ /** * Register the classes */ ClassLoader::addClasses(array ( // Modules 'ModuleScreencastList' => 'system/modules/screencast/modules/ModuleScreencastList.php', )); /** * Register the templates */ TemplateLoader::addFiles(array ( 'mod_screencast_list' => 'system/modules/screencast/templates', ));
autoload.ini
;; ; Configure what you want the autoload creator to register ;; register_namespaces = true register_classes = true register_templates = true
Geschafft!
Wenn ich mich nicht verschrieben habe und ihr alles richtig gemacht habt, könnt ihr eure Screencast-Modul nun einsetzen.
Ausblick
Im folgenden Teil wird unser Modul erweitert. Dabei geht es schwerpunktsmässig um das Hinzufügen von sog. Subpaletten, die eine kontextsensitive (schönes Wort) Auswahl von Einstellungen im Modulbereich erlauben. Zu Deutsch: Wenn der Nutzer die Wahl zwischen verschiedenen Screencast-Quellen (z.B. Youtube, Vimeo etc.) hat, verändern sich die folgenden Eingabe-/Auswahlfelder.
Das Video könnt ihr euch hier schon ansehen: Videolink : DCA Paletten und Subpaletten, MetaPalettes
So...ich habe erstmal fertig. Bis demnächst. Grüße von kobajashi