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:
123456 # Externe Magento-Module:/.modman# Sonstiger externer Code:/vendor# Web Root:/wwwDiese Verzeichnisse werden mit
composer install
undmodman 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:
1 2 3 |
config.vm.synced_folder "./www", "/home/vagrant/www", type: "rsync", rsync_args: ["--verbose", "--archive", "--delete", "-z", "--no-links", "--omit-dir-times", "--no-o", "--no-g", "--no-p"], rsync__exclude: [".git/", "/media/", "/var/", "/tmp/"] |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
#!/bin/sh # synchronize relevant source files to host. if ! getopts "y" opt; then exec < /dev/tty while true; do echo '33[33mFiles have changed in the repository. Synchronize to host? 33[32m[Y/N]33[0m ' read yn case $yn in [Nn]* ) exit; break;; [Yy]* ) break;; * ) echo "Type Y or N" esac done fi # 1) One-way sync., ignore all symlinks: echo '33[1mDirect Sync: vendor33[0m' rsync --verbose --archive --delete -z --no-links --omit-dir-times --no-o --no-p --no-g --exclude=".git" --exclude=".gitkeep" /home/vagrant/</span></code><code class="western"><span style="font-weight: normal"><span style="background: transparent">magento</span></span></code><code class="western"><span style="background: transparent">/vendor/ /vagrant/vendor/ | sed -n '/^skipping non-regular file/!p' echo '33[1mDirect Sync: www33[0m' rsync --verbose --archive --delete -z --no-links --omit-dir-times --no-o --no-p --no-g --exclude=".git" --exclude="/var" --exclude="/media" --exclude=".gitkeep" /home/vagrant/magento/www/ /vagrant/www/ | sed -n '/^skipping non-regular file/!p' # 2) Indirect sync. for rsync shared folders to avoid conflicts mkdir /tmp/magento echo '33[1mSync to /tmp/magento: build33[0m' rsync --verbose --archive --delete -z --no-links --omit-dir-times --no-o --no-p --no-g --exclude=".git" --exclude="/vendor/bin" /home/vagrant/magento/build/ /tmp/magento/build/ echo '33[1mSync to /tmp/magento: src33[0m' rsync --verbose --archive --delete -z --no-links --omit-dir-times --no-o --no-p --no-g --exclude=".git" /home/vagrant/magento/src/ /tmp/magento/src/ echo '33[1mSync from /tmp/magento: build33[0m' rsync --verbose --archive --delete -z --no-links --omit-dir-times --no-o --no-p --no-g --exclude=".gitkeep" /tmp/magento/build/ /vagrant/build/ echo '33[1mSync from /tmp/magento: src33[0m' rsync --verbose --archive --delete -z --no-links --omit-dir-times --no-o --no-p --no-g --exclude=".gitkeep" /tmp/magento/src/ /vagrant/src/ |
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:
1 |
@shell cp -ru $MODULE/* $PROJECT/ |
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:
1 |
@import PROJEKTNAME_Base |
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.

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.
Trackbacks/Pingbacks