Seite 3Entwickler-Workshop 2012
Übersicht
● Teil 1: Dateistruktur
● Teil 2: Class-Autoloading
● Teil 3: Models
● Teil 4: API-Änderungen
● Teil 5: Sonstiges
Seite 6Entwickler-Workshop 2012
Die neue Dateistruktur in Contao 3
● system/bin/minify● Komprimierung der .js- und .css-Dateien
● Muss auf der Kommandozeile aufgerufen werden
➔ ./system/bin/minify mootools
● Wie wird komprimiert?● .css-Dateien werden mit dem YUI-Compressor komprimiert
● .js-Dateien werden mit UglifyJS oder dem YUI-Compressor komprimiert
● Was muss installiert werden?● Der YUI-Compressor wird mitgeliefert
● Für UglifyJS muss node.js und npm installiert sein
● Warum brauche ich das?● Falls Plugins angepasst werden müssen, können trotzdem die komprimierten
Dateien verwendet werden (Page Speed)
Seite 8Entwickler-Workshop 2012
Die neue Dateistruktur in Contao 3
● Der interne Cache (system/cache)
Seite 9Entwickler-Workshop 2012
Die neue Dateistruktur in Contao 3
● Was wird gecacht?● system/dca Zusammenfassung der einzelnen Modul-DCA-Dateien
● system/html Fertig gerenderte Frontend-Seiten
● system/language Zusammenfassung der einzelnen Modul-Sprachdateien
● system/search Suchanfragen
● system/sql Die SQL-Anweisungen und Relationen aus den DCA-Dateien
● Warum wird gecacht?● Weniger Festplattenzugriffe
● Weniger RAM-Verbrauch beim Auslesen der SQL-Anweisungen
● Leeren des Cache● Über die Systemwartung
● Über den Automator (Command Scheduler)
Seite 11Entwickler-Workshop 2012
Die neue Dateistruktur in Contao 3
● Deutlich aufgeräumter als in Version 2● „backend“ und „frontend“ wurden als „core“ zusammengefasst
● „registration“, „rss_reader“ und „tpl_editor“ wurden in „core“ integriert
● „rep_base“ und „rep_client“ wurden als „repository“ zusammengefasst
● Das Entwickler-Modul ist wieder im Core● Das „development“-Modul wird wieder mit dem Core ausgeliefert
● Um Missverständnisse zu vermeiden, wurde es in „devtools“ umbenannt
● Das Modul wird in Version 3 auch für Anwender relevant
Seite 13Entwickler-Workshop 2012
Die neue Dateistruktur in Contao 3
● Beliebige Unterordner möglich● Bessere Strukturierung der PHP-Dateien
● Der Mapper-Class-Loader weiß, wo die Dateien liegen
● Beliebige Unterordner (nicht verschachtelt) möglich
● Aufteilung der PHP-Klassen im Core● classes Alles, was nicht in die anderen Kategorien passt
● drivers DC_-Dateien (DC_Table, DC_Folder etc.)
● elements Inhaltselemente
● forms Formular-Felder (Frontend)
● models Model-Klassen
● modules Frontend-Module
● pages Seiten-Klassen (PageRegular, PageRoot etc.)
● widgets Formular-Felder (Backend)
Seite 15Entwickler-Workshop 2012
Die neue Dateistruktur in Contao 3
● Zentraler Library-Ordner● Im Ordner „system/library“ befinden sich alle PHP-Libraries
● Neben dem Contao-Framework liegen dort z.B. auch Swiftmailer und TCPDF
● Im Ordner „plugins“ liegen nur noch JavaScript-Plugins
● Bekannte Strukturen● Die Struktur des Contao-Frameworks hat sich nicht geändert
● Alle Änderungen sind optional und weitestgehend rückwärtskompatibel
Seite 17Entwickler-Workshop 2012
Class-Autoloading in Contao 3
● Mapper-Class-Loader● Bisher: Durchlaufen der Verzeichnisse auf der Suche nach einer Klasse
● Neu: Die Klassen werden registriert und in einem Mapper-Array gespeichert
● Vorteile● Schnelleres Auffinden der Klassen
● Deutliche weniger Festplattenzugriffe
● Beliebige Unterordner zur Strukturierung möglich
● Auch Templates laden dank Mapper schneller
● Warum überhaupt?● Keine einheitlichen Standards für die Benennung von Klassen
● Umstellung auf PSR-0 aus Gründen der Rückwärtskompatibilität nicht möglich
● Grosser Gewinn: Alle (!) Core-Klassen lassen sich überschreiben
Seite 18Entwickler-Workshop 2012
Class-Autoloading in Contao 3
● config/autoload.php● In der autoload.php-Datei werden die Klassen und Templates registriert
● Die Erstellung der Datei erfolgt automatisch über den Autoload-Creator (devtools)
● Idealfall● Da die API in Contao 3 weitestgehend rückwärtskompatibel ist, reicht es oft schon
aus, die autoload.php-Datei erstellen zu lassen, damit eine Contao 2-Erweiterung auch unter Contao 3 läuft
● Getestet u.a. mit der Subcolumns-Erweiterung
● Portierung von Erweiterungen● Erweiterungen, die nicht mehr gepflegt werden, aber z.B. unter Contao 2.11 laufen,
können mit dem Autoload-Creator portiert werden
● Ausnahme: komplexe Erweiterungen mit dynamisch erstellten Klassen
Seite 21Entwickler-Workshop 2012
Class-Autoloading in Contao 3
● Namespaces● Contao 3 nutzt Namespaces, läuft aber im globalen Namespace
● Was heißt das?● Oberstes Ziel: Rückwärtskompatibilität
● Bestehende Erweiterungen laufen im globalen Namespace
● Daher keine Umstellung auf Namespaces möglich
● Warum dann trotzdem „namespace Contao“?● Der Namespace ermöglicht das Überschreiben aller (!) Core-Klassen
● Der Autoloader erstellt einen Alias der gefundenen Klassen aus dem Namespace im globalen Namensraum, mit dem die Applikation arbeitet
● Wird eine gleichlautende Klasse in einem eigenen Namespace gefunden, arbeitet Contao automatisch mit dieser anstatt mit der Core-Klasse
Seite 22Entwickler-Workshop 2012
Class-Autoloading in Contao 3
● Ein Beispiel● Die index.php greift auf die Klasse „Environment“ zu
● Die Klasse „Environment“ existiert nicht im globalen Namespace
● Der Autoloader findet die Klasse im Namenspace „Contao“
● Er erstellt einen Alias der Klasse „Contao\Environment“ im globalen Namespace
● Die Applikation arbeitet mit „Environment“ und nicht mit „Contao\Environment“
● Eigene Environment-Klasse● Erstellen einer eigenen Environment-Klasse
● Diese liegt im Namespace „Custom“ (Custom\Environment)
● Der Autoloader findet die Klasse nun im Namespace „Custom“
● Der Alias im globalen Namespace zeigt jetzt auf „Custom\Environment“
● Die index.php verwendet weiterhin einfach nur die Klasse „Environment“, ohne zu wissen, dass diese jetzt „Custom\Environment“ ist
Seite 29Entwickler-Workshop 2012
Objektorientierter Zugriff auf Datensätze
● Mit Models lassen sich● Datensätze finden
● Datensätze durchlaufen und lesen
● Datensätze verändern
● Datensätze löschen
● Datensätze neu erstellen
● Objektorientierte Verwendung● Ein Datensatz entspricht einem Objekt (Model)
● Mehrere Datensätze werden als mehrere einzelne Objekte (Models) in einer Objekt-Kollektion (Model_Collection) verwaltet
Seite 30Entwickler-Workshop 2012
Objektorientierter Zugriff auf Datensätze
● Neuer Datensatz● $user = new UserModel();$user->name = 'Leo Feyer';$user->location = 'Bad Soden';$user->save();
● Äquivalent zu● $db->prepare('INSERT INTO tl_user SET name=?, location=?') ->execute('Leo Feyer', 'Bad Soden');
Seite 31Entwickler-Workshop 2012
Objektorientierter Zugriff auf Datensätze
● Datensatz ändern● $user = UserModel::findById(4);$user->location = 'Bad Soden';$user->save();
● Äquivalent zu● $db->prepare('UPDATE tl_user SET location=? WHERE id=4') ->execute('Bad Soden');
Seite 32Entwickler-Workshop 2012
Objektorientierter Zugriff auf Datensätze
● Datensatz löschen● UserModel::findById(4)->delete();
● Äquivalent zu● $db->execute('DELETE FROM tl_user WHERE id=4');
Seite 33Entwickler-Workshop 2012
Objektorientierter Zugriff auf Datensätze
● Mehrere Datensätze finden● $users = UserModel::findBy('location', 'Bad Soden');
while ($users->next()){
echo $users->name;}
● Äquivalent zu● $users = db->prepare('SELECT * FROM tl_user WHERE location=?') ->execute('Bad Soden');
while ($users->next()){
echo $users->name;}
Seite 34Entwickler-Workshop 2012
Objektorientierter Zugriff auf Datensätze
● Interface● Um rückwärtskompatibel zu sein, müssen sich Models genauso verhalten wie die
Database-Klassen und implementieren daher auch dieselbe Schnittstelle
● Keine Validierung● Keine Prüfung der Daten des Objekts vor dem Speichern
● Die Validierung erfolgt in Contao auf Controller-Ebene (Widget)
● PHP-Magic● UserModel::findBy('location', 'Bad Soden');
● UserModel::findByLocation('Bad Soden');
● Alles kann, nichts muss● Die Verwendung von Models ist komplett optional
● Es kann auch weiterhin direkt mit der Database-Klasse gearbeitet werden
Seite 35Entwickler-Workshop 2012
Objektorientierter Zugriff auf Datensätze
● Unterstütze Methoden● Finde einen Datensatz
➔ findByPk() Findet einen Datensatz anhand des Primärschlüssels
➔ findOneBy() Findet einen Datensatz anhand der übergebenen Parameter
➔ findOneBy*() Findet einen Datensatz anhand eines bestimmten Feldes
➔ findByIdOrAlias() Findet einen Datensatz anhand seiner ID oder seines Alias
● Finde mehrere Datensätze
➔ findBy() Findet Datensätze anhand der übergebenen Parameter
➔ findBy*() Findet Datensätze anhand eines bestimmten Feldes
➔ findAll() Findet alle Datensätze
● Zähle die Ergebnisse
➔ countBy() Zählt die Ergebnisse einer findBy()-Abfrage
➔ countAll() Zählt die Ergebnisse einer findAll()-Abfrage
Seite 36Entwickler-Workshop 2012
Objektorientierter Zugriff auf Datensätze
● Komplexeres Beispiel● WHERE mit mehreren Spalten (String oder Array)
➔ public static function findPublishedById($intId){
$t = static::$strTable;$arrColumns = array("$t.id=?");
// Zeige nur veröffentlichte Artikelif (!BE_USER_LOGGED_IN){
$time = time();$arrColumns[] = "($t.start='' OR $t.start<$time) AND
($t.stop='' OR $t.stop>$time) AND $t.published=1";}
return static::findOneBy($arrColumns, $intId);}
Seite 37Entwickler-Workshop 2012
Objektorientierter Zugriff auf Datensätze
● Komplexeres Beispiel● FIND_IN_SET()
➔ public static function findMultipleByIds($arrIds){
if (!is_array($arrIds) || empty($arrIds)){
return null;}
$arrIds = implode(',', array_map('intval', $arrIds));
$t = static::$strTable;$db = \Database::getInstance();
return static::findBy(
array("$t.id IN(" . $arrIds . ")"),null,array('order'=>$db->findInSet("$t.id", $arrIds))
);}
Seite 38Entwickler-Workshop 2012
Objektorientierter Zugriff auf Datensätze
● Relationen● Die Seite zu einem Artikel finden
➔ $article = ArticleModel::findById(12);$page = $article->getRelated('pid');
● $page ist jetzt ein Objekt vom Typ PageModel
● Eager oder lazy loading● Wird ein in Beziehung stehendes Objekt „eagerly“ geladen, erstellt der QueryBuilder
automatisch ein JOIN-Query und lädt beide Objekte in einer Datenbank-Abfrage
● Wird ein in Beziehung stehendes Objekt „lazy“ geladen, wird es erst auf Anfrage in einer separaten Datenbank-Abfrage nachgeladen
● Einheitliches Interface● Die Methode getRelated() lädt das in Beziehung stehende Objekt, egal ob die Daten
bereits „eagerly“ geladen wurden, oder noch „lazy“ nachgeladen werden müssen
Seite 40Entwickler-Workshop 2012
Objektorientierter Zugriff auf Datensätze
● Was passiert im Hintergrund?● Zu jedem Artikel wird automatisch der Autor geladen
● Der Model_QueryBuilder erstellt automatisch eine JOIN-Abfrage
➔ SELECT … FROM tl_article LEFT JOIN tl_user ON …
● $article->getRelated('author') gibt das Benutzer-Model zurück
● Beim Aufruf von getRelated() muss keine DB-Abfrage ausgeführt werden
● Das dazugehörige Seiten-Model● Die übergeordnete Seite ist „lazy related“
● Sie wird nicht automatisch per JOIN zum Result-Set hinzugefügt
● $article->getRelated('pid') gibt das Seiten-Model zurück
● Beim Aufruf von getRelated() wird im Hintergrund eine DB-Abfrage ausgeführt
➔ SELECT * FROM tl_page WHERE id=?
Seite 42Entwickler-Workshop 2012
API-Änderungen in Contao 3
● Statische Methoden● Deklaration nicht-objektbezogener Methoden als statisch
● Contao 2● $this->import('String');echo $this->String->substr($string, 24);
● Contao 3● echo String::substr($string, 24);
● Rückwärtskompatibilität● Auch die Variante aus Contao 2 funktioniert in Contao 3
● Alle Änderungen sind optional und müssen nicht übernommen werden
Seite 43Entwickler-Workshop 2012
API-Änderungen in Contao 3
● Betroffene Klassen● Cache Nicht-persistente Speicherung von Daten
● Encryption Verschlüsselung
● Environment Umgebungsvariablen auslesen ($_SERVER)
● Input Benutzereingaben auslesen ($_GET, $_POST, $_COOKIE)
● RequestToken Request-Token erstellen und prüfen
● Search Suchindex erstellen und Suchabfragen ausführen
● String String-Manipulation
● Neue hinzugekommen● Idna Internationale Domainnamen
● Image Bilder verkleinern
● Message Meldungen im Backend ausgeben
● Validator Prüfung auf bestimmte Formate anhand regulärer Ausdrücke
Seite 47Entwickler-Workshop 2012
API-Änderungen in Contao 3
● Wegfall der database.sql● Die database.sql-Dateien werden nicht mehr benötigt
● Datenbank-Definitionen können direkt im DCA eingegeben werden
● Rückwärtskompatibilität● database.sql-Dateien funktionieren weiterhin auch in Contao 3
● Die Umstellung ist wie bei allen anderen Änderungen optional
Seite 49Entwickler-Workshop 2012
API-Änderungen in Contao 3
● Eigene Edit-Buttons● Neue Sektion im DCA zum Hinzufügen eigener Buttons● $GLOBALS['TL_DCA'][…]['edit']['buttons_callback']
● Beispiel: Aliase generieren● Datei system/modules/core/dca/tl_page.php
● Der Callback addAliasButton() fügt das Markup und die Logik hinzu
Seite 52Entwickler-Workshop 2012
Sonstige Änderungen im Kurzüberblick
● Datenbank-Adapter● Zukünftig stehen nur noch MySQL und MySQLi zur Verfügung
● Die anderen Adapter wurden entfernt, da sich in den letzten 6 Jahren niemand gefunden hat, der diese vervollständigt hätte
● Minütliche automatisierte Aufgaben● Der Command Scheduler wurde um das Intervall „minütlich“ erweitert
● Achtung: Erfolgt der Trigger nicht über einen Cronjob, kann die minütliche Ausführung nicht garantiert werden!
● Inaktive Erweiterungen● Deaktivierung durch Hinzufügen einer Datei namens .skip
● Kein Speichern der inaktiven Erweiterungen in der Konfigurationsdatei mehr, damit diese nicht doppelt geladen werden muss
Top Related