Webbasierte Software für für E-Sport und Business

Symfony 2 Bundle Konfiguration und Kopplung // Teil 1 - Abhängigkeiten

Veröffentlicht von am 13.07.2016

In dieser Blog-Reihe zeigen wir Ihnen, wie Sie Symfony Werkzeuge sinnvoll in Ihrer Agentur für die Erstellung von eigenen Bundles einsetzen können. Dabei steht die Modularität und Anpassungsfähigkeit im Vordergrund. Damit sind Sie nicht nur in der Lage, Ihr eigens entwickeltes Bundle in weiteren Projekten wiederzuverwenden, sondern Sie profitieren gleichzeitig von einer erhöhten Wartbarkeit. In diesem Teil werden wir Ihnen zeigen, wie Abhängigkeiten zwischen Bundles in Symfony definiert und verwaltet werden.

Der Name Symfony stellt die Struktur des Frameworks sehr literarisch dar: Lediglich der äußere Rahmen wird vorgegeben. Die restlichen Komponenten i.d.R. sogenannte Bundles werden dynamisch durch das Tool Composer verwaltet, dessen Bedeutung und Konfiguration im Laufe dieses Beitrags beleuchtet wird.

Warum Bundles?

Module oder Komponenten sind in der Informatik ein bekanntes Werkzeug, um komplizierte Software in kleinere Teile herunterzubrechen. Dabei sind Bundles in Symfony bereits recht große, eben gebündelte Pakete. In diesen werden unter anderem kleinere Komponenten wie z.B. sogennante Components oder aber auch einzelne logische Elemente z.B. Services untergebracht.

Diese modulare Struktur bringt sowohl Ordnung in die unzähligen Komponenten als es auch viele Möglichkeiten zur Erweiterbarkeit bzw. Überschreibung zwischen Bundles ermöglicht.

Ersteres sorgt in Verbindung mit den Symfony-Konventionen für eine gute Wartbarkeit, während letzteres die Wiederverwendbarkeit der Bundles begünstigt.

Jedoch besitzt diese Aufspaltung den unvermeidbaren Effekt, dass Abhängigkeiten entstehen.

Diese Abhängigkeiten müssen verwaltet und auch aufgelöst werden können. Symfony setzt hierbei auf das Tool Composer, welches auf Packagist als Paket bzw. Bundle-Verzeichnis setzt.

Abhängigkeiten von Bundles

Wie bereits erwähnt wird Composer zur Abhängigkeitsauflösung verwendet. In diesem Zusammenhang wird auch die Abhängigkeitsspezifikation von Composer übernommen und in Konfigurationsdateien composer.json definiert:

Hinweis: Auch das Symfony-Projekt besitzt eine eigene composer.json, über die die Projekt-Abhängigkeiten (unter anderem Symfony Core) definiert werden.

{
    "name": "friendsofsymfony/user-bundle",
    "type": "symfony-bundle",
    "description": "Symfony FOSUserBundle",
    "require": {
        "php": ">=5.3.2",
        "symfony/framework-bundle": "~2.1",
        "symfony/security-bundle": "~2.1"
    },
    "suggest": {
        "willdurand/propel-typehintable-behavior": "Needed when using the propel implementation"
    },
}
composer.json

In diesen Konfigurationsdateien sind grundlegende Informationen über das Bundle und z.B. die Autoren vermerkt. Für Composer ist jedoch die require-Sektion von viel größerer Bedeutung.

Hier können und sollten die entsprechenden Abhängigkeiten des Bundles aufgeführt und nach Möglichkeit in der Versionsnummer eingeschränkt werden, um Folgen von Breaking-Changes durch Major-Versionsupdates für das eigene Bundle und damit eventuell Fehlern in von diesem Bundle abhängigen weiteren Bundles oder ganzen Projekten entgegen zu wirken.

Weiterhin ist die Sektion suggest interessant. In diesem oft wenig genutzten Teil der Spezifikation können optionale Abhängigkeiten definiert werden:

Optionale Abhängigkeiten

Dieses Mittel erlaubt eine lose Kopplung von Bundles untereinander und kann genutzt werden, um die Funktionen eines Bundles zu erweitern oder Funktionen anderer Bundles zu integrieren:

Für den Anfang betrachten wir ein Beispiel unter Nutzung des Symfony-Event-Systems, das wir uns später genauer ansehen werden. In folgenden Teilen werden wir zudem eine in bestimmten Fällen elegantere Möglichkeit mithilfe von Service-Compiler-Passes erläutern.

/**
* Fires an event for any activity listener
* @param $type
* @param null $data
* @param null $user
*/
protected function activityEvent($type, array $tags = array(), $data = null, $user = null) {

    if(!class_exists('BrauneDigital\ActivityBundle\Event\ActivityEvent')) {
        throw new \Exception("You need to install the BrauneDigitalActivityBundle to use this function!");
    }

    if(!$user) {
        $user = $this->getUser();
    }
    //fire login event
    $event = new ActivityEvent($type, $user, $tags, $data);
    $this->get('event_dispatcher')->dispatch(ActivityEvent::EVENT_ID, $event);
}

Ausblick

Im nächsten Teil werden wir uns mit Service-Tags beschäftigen. Dabei steht wie angedeutet auch dort die Zusammenarbeit zwischen Bundles im Vordergrund.

© 2021, Braune Digital GmbH, Niemannsweg 69, 24105 Kiel, +49 (0) 431 55 68 63 59