Contao 3 mit Symfony-Komponenten

von Patrick Froch (Kommentare: 0)

In diesem Artikel wird beschrieben, wie man Symfony-Komponenten in Contao 3 nutzen kann. Es wird in einer kleinen Beispielanwendung gezeigt, wie man Einstellungen aus YAML-Dateien laden und in Contao verwenden kann.

Die hier gezeigte Beispiele sollen nur das Prinzip verdeutlichen. Die Details der Implementierung können sicher noch optimiert werden. Es wurde aber bewusst eine einfache Art der Programmierung gewählt, um auch Anfängern das Verständnis zu erleichtern.

Verzeichnisstruktur

Zunächst wird ein Verzeichnis für die Erweiterung unter TL_ROOT/system/modules/ angelegt. Ich nenne es jetzt einmal yamldemo. Der Name kann natürlich frei gewählt werden.

Seit Contao 3 kann man seine Klassen in diesem Verzeichnis ablegen wo man möchte. Contao selbst speichert z.B. die Klassen der Inhaltselemente im Verzeichnis elements. Ich finde dieses Vorgehen suboptimal, deshalb speichere ich alle Klassen im Verzeichnis classes. Normalerweise gibt es dort noch verschiedene Unterordner, die die Klassen gruppieren. Der Übersicht halber, werden die zwei Klassen in diesem Beispiel direkt in classes gespeichert. Es ergibt sich für das Projekt folgende Verzeichnisstruktur:

Verzeichnisstruktur

Ich werde in diesem Beitrag nicht auf alle Dateien eingehen. Einige sind nur für Contao nötig, wie z.B. languages/de/default.php. Andere werden automatisch erzeugt, wie z.B. composer.lock. Die Datei classes/ContentYaml.php erzeugt nur eine Ausgabe, die ich zur Kontrolle benutzt habe. Wenn man die Symfony-Komponenten installiert hat, wird es noch einen Ordner vendor geben. Dort legt Composer alle Dateien ab.

Installation der Komponenten

Für die Installation der Komponenten wird composer verwendet. Wie dies im einzelnen funktioniert wurde bereits in dem Artikel: " Composer - Die Grundlagen " beschrieben, deshalb werden hier nur in aller Kürze die nötigen Schritte aufgezeigt:

Erstellen der composer.json in dem eben angelegten Verzeichnis (bei mir TL_ROOT/system/modules/yamldemo/composer.json) mit folgendem Inhalt:

{
    "require": {
        "symfony/finder": "2.6.*@dev",
        "symfony/yaml": "2.6.*@dev"
    }
}
Die Installation wird über die Kommandozeile wie folgt ausgeführt:
$> cd TL_ROOT/system/modules/yamldemo
$> php composer.phar install
(TL_ROOT muss durch den Pfadt der Contao-Installation ersetzt werden, yamldemo durch den Namen des erstellten Verzeichnisses.)
Das war schon alles.

Autoload

Damit man nun Zugriff auf die Symfony-Komponenten hat, ist der einfachste Weg am Ende der Datei config/autoload.php folgende Zeile einzufügen:
    include TL_ROOT . "/system/modules/yamldemo/vendor/autoload.php";
(Hier wird TL_ROOT nicht geändert, yamldemo muss wieder gegen den Namen des erstellten Ordners ausgetauscht werden.)
So wird der Composer-Autoloader eingebunden und man muss sich um nichts weiter kümmern.

YAML

YAML ist eine vereinfachte Auszeichnungssprache (englisch markup language) zur Datenserialisierung, angelehnt an XML (ursprünglich) und an die Datenstrukturen in den Sprachen Perl, Python und C sowie dem in RFC 2822 vorgestellten E-Mail-Format. Die Idee zu YAML stammt von Clark Evans, die Spezifikation wurde von ihm selbst, Brian Ingerson und Oren Ben-Kiki erstellt. YAML ist ein rekursives Akronym für „YAML Ain’t Markup Language“ (ursprünglich „Yet Another Markup Language“).

(Quelle: http://de.wikipedia.org/wiki/YAML)

Ich verwende in diesem Beispiel folgende YAML-Datei:

testString: Dies ist ein Teststring!

testArray:
  - Erster Eintrag
  - Zweiter Eintrag
  - Dritter Eintrag

"NochEinArray":
  Eins: TestEins
  Zwei: TestZwei
  Drei: TestDrei
Die Datei enthält sowohl einen String, eine Liste und eine assoziative Liste.

Nutzung der Komponenten

Der Finder

Die Nutzung in eigenen Klassen ist durch den Autoloader denkbar einfach. Um alle YAML-Dateien zu laden, die in den config-Ordnern in den Modulordnern unter TL_ROOT/system/modules/ gespeichert sind, kann man folgende Methode verwenden:
class myYaml
{
    public function loadData()
    {
        // Vorbereitung
        $arrData    = array();
        $strPath    = TL_ROOT . '/system/modules/*/config';

        // Finder erstellen und Dateien suchen
        $objFinder  = new \Symfony\Component\Finder\Finder();
        $objFinder->in($strPath)->sortByName()->files()->name('*.yaml');

        foreach($objFinder as $file) {
            $arrData[$file->getFilename()] = $file->getContents();
        }

        return $arrData;
    }
}

Man erhält ein Array, in dem bereits der Inhalt aller Dateien enthalten ist. Als Schlüssel des assoziativen Array werden die Dateinamen verwendet. Dateien die später kommen überschreiben den Inhalt früherer Dateien. Also so, wie es auch Contao in seiner Config macht. Dies könnte man mit wenig Aufwand auch ändern, aber als Beispiel soll dies erst einmal reichen.

In Zeile 10 wird eine Instanz des Symfony-Finders erstellt und in Zeile 11 werden die Dateien geladen. Das war schon der erste Einsatz einer Symfony-Komponente in Contao.

Die YAML-Komponente

Nun muss aus dem Inhalt der Dateien nur nach ein PHP-Array erzeugt werden. Auch hierfür wird wieder eine Methode erstellt:
class myYaml
{
    public function loadData()
    {
        ...
    }

    public function convertData($arrData)
    {
        if(is_array($arrData))
        {
            foreach($arrData as $strContent)
            {
                $varYaml            = \Symfony\Component\Yaml\Yaml::parse($strContent);
                $this->arrYamlData  = array_merge($this->arrYamlData, $varYaml);
            }
        }

        return $this->arrYamlData;
    }
}
Hier wird das übergebene Array durchlaufen und die einzelnen Einträge durch den Yaml-Parser in Zeile 14 in ein Array umgewandelt. Das die Ergebnisse der Umwandlung hier in einer Klasseneigenschaft gespeichert werden, hat nur den Grund, damit man noch eine Methode implementieren kann, mit der man direkt einzelne Werte auslesen kann. Dies würde hier aber zu weit führen.

Verwendung der yaml-Klasse

Hier nun noch ein Beispiel für die Nutzung der yaml-Klasse:
class myYaml
{
	/**
	 * Die Methode lädt die Daten der YAML-Datein.
	 */
    public function loadData()
    {
        // Vorbereitung
        $arrData    = array();
        $strPath    = TL_ROOT . '/system/modules/*/config';

        // Finder erstellen und Dateien suchen
        $objFinder  = new \Symfony\Component\Finder\Finder();
        $objFinder->in($strPath)->sortByName()->files()->name('*.yaml');

        foreach($objFinder as $file) {
            $arrData[$file->getFilename()] = $file->getContents();
        }

        return $arrData;
    }


	/**
	 * Die Methode konvertiert die YAML-Daten in ein PHP-Array.
	 */
    public function convertData($arrData)
    {
        if(is_array($arrData))
        {
            foreach($arrData as $strContent)
            {
                $varYaml            = \Symfony\Component\Yaml\Yaml::parse($strContent);
                $this->arrYamlData  = array_merge($this->arrYamlData, $varYaml);
            }
        }

        return $this->arrYamlData;
    }
}


/**
 * Beipsiel für die Benutzung
 */
$yaml 		    = new myYaml();
$arrFileContent = $yaml->loadData();
$arrData		= $yaml->convertData($arrFileContent);

echo $arrData['testString'];	// OUTPUT: Dies ist ein Teststring!
Natürlich gibt es hier noch viel Optimierungsbedarf. Die Klasse wurde absichtlich einfach gehalten. Es sollte nicht die Erstellung einer ausgereifte Klasse demonstriert werden, sonder die Verwendung der Symfony-Komponenten. Diese beschränken sich auf nur 3 Zeilen, der Overhead durch die Klasse ist also auch so schon große genug. Dies zeigt aber auch wie einfach die Arbeit mit Symfony sein kann.

Zurück

Einen Kommentar schreiben