Im ersten Teil der Artikelserie zu Magento mit Vagrant habe ich Vagrant und die automatische Synchronisation mit Rsync vorgestellt, im zweiten Teil ein einfaches Basis-Setup der Vagrantbox für Magento. In diesem Teil soll es nun um die Projektstrukturierung gehen.

Mögliche Strukturen, aufbauend auf dem Basis-Vagrant-Setup:

Eigener Code separiert von Core und Extensions in src/

Das meiner Meinung nach ideale Setup habe ich im letzten Beitrag bereits beschrieben:

Die hier vorgestellte Struktur empfehle ich für neu entwickelte Shops. Mögliche Alternativen werden in einem separaten Beitrag erläutert. Der Quellcode verteilt sich auf folgende Verzeichnisse:

Verzeichnis Inhalt
/.modman Magento-Extensions
/src Projektspezifischer Code (inkl. gekaufter Extensions)
/vendor Nicht-Magento-spezifische Bibliotheken
/www Magento-Core

Durch Modman werden auf der Vagrantbox zusätzlich Symlinks in .modman (nach src) und www (nach .modman) erstellt.

In /www/ gibt es also keinerlei custom code, alles kommt mit Composer und Modman entweder aus /vendor bzw. /.modman (für fremden Code und eigene, projektübergreifende Module) oder aus /src (für eigenen, shop-spezifischen Code).

Im Git Repository befindet sich nur der eigene Code sowie Abhängigkeitsdefinitionen und Installations-Anweisungen. Auszug aus der .gitignore:

Diese Verzeichnisse werden mit composer install und modman deploy befüllt. Anmerkung: Es hat auch Vorteile, .modman und vendor mit ins Repository aufzunehmen, damit entfällt das oft langwierige composer install beim Umschalten zwischen Branches und die Verfolgung von Änderungen durch Updates wird einfacher.

Ich benutze https://github.com/AOEpeople/composer-installers als leichtgewichtige Alternative und Drop-in-Replacement zum Magento Composer Installer. Magento Extensions werden damit direkt nach .modman statt vendor heruntergeladen und können von dort ganz normal mit modman deployed werden, frei nach der Unix-Philosophie „one simple tool for each job“. Mehr Infos dazu gibt es in der Präsentation “Wiring Magento Projects“: http://de.slideshare.net/aoepeople/merged-32876900

In /src liegt eine zentrale modman-Datei, die alle eigenen Module mit @import importiert. So muss nur src selbst mit „modman link“ in .modman verlinkt werden. Daher habe ich im oben vorgestellten Vagrantfile bei den Synchronisations-Einstellungen für .modman auch /src exkludiert, dies ist der einzige in .modman angelegte Symlink, alle mit Composer installierten Module sind wie gesagt direkt hier installiert.

Vorteile:

  • Strikte Trennung von Core, 3rd-Party Modulen und Eigenentwicklungen
  • Komplett modular, der Modul-Code ist jeweils an einer Stelle gesammelt

Alternative 1: Vollständiger Shop in Git Repository

Das ist häufig der Fall bei Projekten, an denen bereits andere Firmen gearbeitet haben oder arbeiten. Das Git Repository bildet hier 1:1 den Code auf dem Server ab, es wird kein Gebrauch von Tools wie Modman oder Composer gemacht.

Die einfachste Weise, mit einem solchen Projekt auf der Box loszulegen, ist, das Repository als Submodul in www hinzuzufügen. Die Verzeichnisse vendor und src bleiben ungenutzt, im Vagrantfile muss nun allerdings die Synchronisation von www eingerichtet werden. Dies kann z.B. so aussehen:

Evtl. müssen die rsync-Parameter angepasst werden, um weitere Verzeichnisse von der Synchronisation auszuschließen.

Vorteil:

  • Mit diesem Setup kann die Code Completion des PhpStorm Plugins Magicento voll ausgeschöpft werden, da es so alle Modulkonfigurationen einlesen kann (seit dem neuesten Update funktioniert das auch mit getrennten Verzeichnissen, diese müssen nur alle einzeln angegeben werden)
  • Schneller Umstieg mit existierendem Projekt

Nachteil:

  • Trennung von Core und Modulen sowie Modulen untereinander fehlt.

Alternative 2: Vollständiger Shop in Git Repository mit Modman

Das ist eine Variante, die sich niemand, der unter Windows entwickelt, freiwillig aussucht, einfach weil Git unter Windows nicht mit Symlinks arbeiten kann. Die Idee ist, mit modman zu entwickeln und das Gesamt-Ergebnis ins Repository zu committen, sprich die Quellen z.B. in /src/ und die von modman generierten Symlinks im Magento-Verzeichnis, z.B: /www/.

Hier führt kein Weg daran vorbei, das Repository nur auf der Vagrantbox auszuchecken und dort mit Git zu arbeiten. Auf die Git-Integration in der IDE oder einen grafischen Client auf dem Host muss man hier also leider verzichten. Zusätzlich benötigen wir eine Synchronisation von der Box zum Host, so dass wir gepullte Änderungen mitbekommen. Das habe ich über einen post-receive Hook erreicht:

Die Verzeichnisse, die Vagrant über Rsync synchronisiert, werden hierbei mit Umweg über /tmp übertragen. Andernfalls würde sobald die erste Datei übertragen ist, der Rsync Watcher auf dem Host anspringen und das Verzeichnis zurück auf die Box synchronisieren, wodurch alle weiteren Änderungen wieder überschrieben werden.

Nach Änderungen im Repository, die anders zustande gekommen sind (z.B. Stash, Merge), kann der Hook manuell mit git checkout getriggert werden.

Vorteil:

  • Sehr genaue Versionierung, Fehler im Deployment minimiert
  • Strikte Trennung von Core, 3rd-Party Modulen und Eigenentwicklungen
  • Komplett modular, der Modul-Code ist jeweils an einer Stelle gesammelt

Nachteil:

  • Umständliche Synchronisation
  • Git nur auf der Vagrantbox

Alternative 3: Bestehender Shop als Einheit, neu entwickelte Module mit modman

Dieses Szenario macht Sinn, wenn man die Entwicklung eines bestehenden Shops übernimmt, oder in einem eigenen Projekt modman einführen möchte.

Dazu wird ein Verzeichnis PROJEKTNAME_Base (o.ä.) in /src angelegt, in das der gesamte Original-Code kopiert wird. Dazu kommt eine modman-Datei mit folgendem Inhalt:

Damit wird das gesamte Verzeichnis kopiert (-u sorgt dafür, dass nur neuere Dateien kopiert werden, so dass eventuell durch neue Module ersetzte Dateien nicht versehentlich mit der Originalversion überschrieben werden). Alternativ kann man auch hier rsync (ohne –delete Option) verwenden. Dieses „Modul“ muss wie alle anderen in /src/modman importiert werden:

Neue Module werden wie oben beschrieben in /src/MODULNAME angelegt und gleichermaßen in /src/modman importiert. Bestehende Module können direkt in PROJEKTNAME_Base bearbeitet werden, oder zunächst in ein eigenes Verzeichnis extrahiert und mit modman-Datei versehen werden.

Der Umstieg von „Vollständiger Shop in Git Repository“ ist leicht gemacht, sofern man auf das Original-Repository verzichten kann.

Vorteil:

  • Ermöglicht schrittweise Umstellung auf modulare Code-Basis

Nachteil:

  • Änderungen an bestehenden Modulen sind zunächst umständlich

Extension-Entwicklung

Bei der Entwicklung von Extensions braucht man ein eigenes Extension-Repository. Am besten geht das mit dem Basis-Setup und einem Submodul unterhalb von /src/ für die Extension. Mit Vagrant kann sie auch gut in verschiedenen Umgebungen getestet werden, entweder mit separaten Boxen oder durch Anpassung in der Provisionierung.
Ich empfehle das anlegen von mehreren Magento-Installationen auf einer Box, z.B. www1.9 www1.8 www1.7 usw., mit entsprechend separaten Datenbanken. Eines der Verzeichnisse wird dann jeweils nach www gelinkt und durch das Umbiegen des Symlinks kann einfach von Version zu Version gewechselt werden. Modman deployed immer nach www, muss dann also nicht umkonfiguriert werden.

Diskussion

Kritik, Ideen und Ergänzungen sind herzlich willkommen. Wie wir alle wissen, hat man die perfekte Struktur niemals gefunden.

Im nächsten Beitrag kommen wir zum Thema Puppet als Provisioner. Die Shell-Skripte aus dem letzten Beitrag entfallen damit größtenteils zugunsten einer robusteren Lösung. An der hier Strukturierung des Quellcodes ändert sich dadurch jedoch nichts.

Fabian Schmengler

Author: Fabian Schmengler

Fabian Schmengler ist Diplom-Informatiker und Magento Entwickler bei integer_net. Seine Schwerpunkte sind Backend-Entwicklung, Konzeptionierung und Test-Automatisierung. Seit 2011 ist er Magento Certified Developer, seit 2014 Magento Certified Solution Specialist.