An sich geht es ganz einfach. In der Administration geht man auf Update, bestätigt alles, die Plugins werden deaktiviert (vielleicht auch das Language-Pack) und dann startet der Installer und .. läuft in einen Fehler und dann läuft garnichts mehr. Scheint jeden Falls öfters mal so zu passieren.
Ich hab mir ein Script gebastelt mit dem man sich eine Kopie des Shops auf die neue Version updaten kann und dann später auf diese Kopie switchen kann.
Man muss nicht alle Plugins deaktiveren, aber einfacher ist es. Also eine Kopie (Dateien und Datenbank) anlegen und da alles Plugins deaktiveren. Per SQL-Statement geht es recht schnell und einfach.
Der original Shop liegt in shop/ und der neue in shop65/. Die .env der Kopie (wegen DATABASE_URL) wird in shop_shared/ abgelegt und um LOCK_DSN="flock" und SHOPWARE_SKIP_WEBINSTALLER=1 ergänzen.
Dann das Script laufen lassen.. oder besser Zeile für Zeile per Hand ausführen.
cd ~/public_html/shop65 && composer update
cd ~/public_html/shop65 && bin/console system:update:finish
cd ~/public_html/shop65/vendor/shopware/administration/Resources/app/administration && npm install && cd ~/public_html/shop65
Ziel ist es wieder in die Administration zu kommen und dort alle Plugins zu aktualisieren. Wenn das gelungen ist, dann alle nach und nach wieder aktivieren und wieder die Themes in den SalesChannels einrichten.
Wenn Fehler auftreten immer mal wieder bin/console aufrufen, weil dann die Exceptions meistens ganz gut dargestellt wird.
So kommt man auch sehr gut ohne den Installer zu seinem aktuellen Shopware und räumt auch direkt noch etwas auf.
Lizenzen einsammeln, die man in seinen Projekten benutzt, kann manchmal nötig sein. Gerade wenn man Software für andere
entwickelt, kann sich der Kunde dafür interessieren, weil den es ja einschränken könnte, wie er die Software verwendet.
Das geht mit diesen Libs relativ einfach.
PHP:
composer global require comcast/php-legal-licenses
~/.config/composer/vendor/bin/php-legal-licenses generate
Jeder der schon mal mit PHP zu tun hatte wird sicher die Installationsanleitung von getcomposer.org. Das Problem ist nur, dass seit einiger Zeit Composer 2.0 installiert wird und einige alte Projekte damit echt ihre Probleme haben. Aber wie installiert man sich eine bestimmte Version? So das nicht plötzlich der Docker-Container nach einem neuen Build eine andere Composer-Version hat und die Pipeline nicht mehr funktioniert.
Man kennt Systeme wie Satis oder Toran die sich aus einem Git bei Änderungen den aktuellen Stand holen und ihn in Versionen für die Libs umwandeln. Man darf nicht vergessen die System zu triggern, um immer die aktuellen Version zu haben. Sonst ändert man was und wundert sich, dass sich nichts ändert.
Mit Gitlab kann man alles in einem haben und das in sehr einfach. Auto DevOps ist aber diesmal nicht die Lösung. Aber man braucht nur ca. 1 Minute um alles einzurichten.
1) Package Repository aktivieren (wenn noch nicht so)
2) Pipelines aktivieren (unwahrscheinlich dass es noch nicht ist)
3) auf der Startseite des Projekt "Setup CI" wählen
4) Bei den Templates "composer" auswählen und mergen
5) .. fertig
Schon findet man beim nächsten Push eines Branches oder Tags in der Package-Registry einen Eintrag für einem Composer-Package.
Plugins für Shopware 6 zu schreiben ist an sich garnicht so unterschiedlich zu dem selben Vorgang für Shopware 5. Was nur anders geworden ist, dass Shopware eigene XMLs und Enlight-Components durch den Composer und Symfony abgelöst wurden. Man kann nun wirklich Namespaces definieren, die unabhängig vom Plugin-Namen sind und es ist kein Problem mehr den Composer mit Plugins zu verwenden, sondern es ist jetzt der zu gehende Weg.
Setup
Wie gehabt kann man sein Plugin unter custom/plugins anlegen.
custom/plugins/HPrOrderExample
Zu erst sollte man mit der composer.json anfangen.
Wichtig in der composer.json ist einmal der PSR-4 Namespace den man auf das src/ Verzeichnis setzt und der "extra" Teil. Dort wird alles definiert, was mit Shopware zu tun hat. Hier wird auch die zentrale Plugin-Class angegeben, die nicht mehr wie in Shopware 5 den selben Namen des Verzeichnisses des Plugins haben muss. Auch sieht man hier dass der Namespace-Name nichts mehr mit dem Verzeichniss-Namen zu tun hat.
Wir könnten durch die composer.json das Plugin auch komplett außerhalb der Shopware-Installation entwickeln, weil die gesamte Plattform als Dependency eingebunden ist. Deswegen müssen wir auch einmal den Composer ausführen.
php composer install
Plugin programmieren Nun fangen wir mit dem Schreiben des Plugins an.
Die Plugin-Klasse enthält erst einmal keine weitere Logik:
<?php
namespace HPr\OrderExample;
use Shopware\Core\Framework\Plugin;
class OrderExample extends Plugin{
}
Wir wollen auf ein Event reagieren. Dafür benutzen wir eine Subscriber-Klasse. Während man diese in Shopware 5 nicht unbedingt brauchte und alles in der Plugin-Klasse erldedigen konnte, muss man nun eine extra Klasse nutzen und diese auch in der services.xml eintragen. Die Id des Services ist der fullqualified-classname des Subscribers
Resources ist vordefiniert, kann aber in der Plugin-Klasse angepasst werden, so dass diese Dateien auch in einem anderen Package liegen könnten.
src/Subscribers/OnOrderSaved
<?php
namespace HPr\OrderExample\Subscribers;
use Shopware\Core\Checkout\Order\OrderEvents;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class OnOrderSaved implements EventSubscriberInterface {
/**
* @return array The event names to listen to
*/
public static function getSubscribedEvents()
{
return [
OrderEvents::ORDER_WRITTEN_EVENT => ['dumpOrderData']
];
}
public function dumpOrderData(EntityWrittenEvent $event) {
file_put_contents('/var/test/orderdump.json', json_encode($event->getContext()));
}
}
Hier sieht man, dass nur noch Symfony benutzt wird und keine Shopware eigenen Events.
Wir schreiben einfach die Order-Entity, die gespeichert wurde in eine Datei. Dort können wir UUID und ähnliches der Order finden.
Das ganze kann man dann weiter ausbauen und auf andere Order-Events (die man alle in der OrderEvents.php finden kann) reagieren.
Installieren
Damit ist das Plugin auch schon soweit fertig. Den Composer haben wir schon ausgeführt (ansonsten müssen wir es spätestens jetzt machen).
Nun geht es über die UI oder die Console weiter. Dort wird das Plugin installiert und und aktiviert.
Wenn man nun eine Bestellung ausführt wird, deren Entity in die oben angegebene Datei geschrieben.
Der einfachste Weg einen Shopware Shop zuinstallieren war immer, die ZIP-Datei mit dem Webinstaller downzuloaden und diese in das gewünschte Verzeichnis zu entpacken. Dann die URL aufrufen und dem Installer folgen. Das ist für automatische Deployments nicht so toll und oft wurde dort einfach die Git-Version verwendet. Die hat den extremen Nachteil, dass diese unglaublich viele Dinge mitbringt, die in einer produktiven Umgebung nichts zu suchen haben. Buildscripte, Tests, etc bringen einen wirklich nur in der Dev-Umgebung was und sollten in der produktiven Umgebung nicht mit rumliegen, weil je mehr rumliegt, desto mehr Sicherheitslücken oder ungewollte Probleme könnten mitkommen.
Seit einiger Zeit kann man Shopware aber auch sehr einfach über den Composer installieren. Dabei wird eine eher moderne Verzeichnisstruktur angelegt und auch die Basis-Konfiguration kann einfach über Env-Variablen gesetzt werden, so dass ein automatisches Deployment für einen Server damit sehr einfach wird. Im Idealfall hat man die Datenbank schon sauber und fertig vorliegen. Dann erspart man sich fast den gesamten Installationsprozess und kann direkt loslegen.
Wenn man den Composer noch nicht installiert hat, muss man diesen kurz installieren:
<Directory /var/www/your_webshop>
AllowOverride All
Require all granted
</Directory>
RewriteEngine On
</Virtualhost>
Reload des Apache und schon kann es an sich losgehen. Wenn man sehen möchte wie die DATABASE_URL verarbeitet wird, kann man einen Blick in die etwas komplexer gewordene config.php werfen die man nun unter your_webshop/app/config/config.php findet.
Sollte man noch keine fertige Datenbank auf dem Server liegen haben, muss man die ./app/bin/install.sh ausführen. Gerade für mehrere automatische Deployments, würde ich aber die Datenbank einmal local auf meiner Workstation anlegen und mit Default-Werten befüllen. Diese kommt dann auf den Datebankserver und wird beim deployment, mit den spezifischen Daten wie den Shopdaten und Admin-Zugängen versehen.
Natürlich würden Updates auch über den Composer laufen, wobei sw:migration:migrate automatisch mit aufgerufen wird, um die Datenbank mit aktuell zu halten. Das Verhalten kann man über die Deaktivierung des entsprechenden Hooks in der composer.json verhindern (aber das macht an sich nur in Cluster-Umgebungen Sinn). Ein Update über das Webinstaller-Plugin würde Probleme bereiten und sollte, wenn man es dann ,z.B. weil man eine alte Installation umgezogen hat, installiert und aktiv hat mit ./bin/console sw:plugin:uninstall SwagUpdate entfernen.
Der wirkliche Vorteil liegt jetzt darin, dass man in die composer.json seine Git-Repositories von den Plugins mit eintragen kann und die Plugins direkt über den Composer installieren und updaten kann. Man muss also nicht diese erst vom Server downloaden + entpacken oder per Git clonen (wo dann wieder viel Overhead mit rüber kommen würde).
Es kann dazu kommen, dass beim Aufruf der console von Shopware 5 keine kernel.environment gesetzt ist. Bei Webserver Aufrufen wird diese ja zumeist in der conf des Apache gesetzt.
Um jetzt die Environment (z.B. "production") direkt beim Aufruf der console zu setzen muss man die Option "e" setzen und schon geht alles.
Hier einmal eine Default-Config für ElasticSearch unter Shopware 5. Gerade mit der Composer-Installation ist es sehr praktisch alle benötigten Felder direkt mal zu sehen.
Manchmal hat man einfach Scripts von anderen, die mit einem Fehlercode beendet werden und es ist vollkommen ok. Leider bricht bei so einem Fehler dann der Build-Process vom Docker-Image ab. Deswegen muss man den Fehlercode überschreiben.
RUN composer create-project shopware/composer-project my_shop --no-interaction --stability=dev; exit 0
Damit wird der Fehler wegen fehlender .env-Datei übergangen. Da man diese Datei an sich auch nicht braucht.
Danach sollte auf localhost:8000 der Shop starten.. wenn eine MySQL Auth.-Method Fehlermeldung kommt hilft die Container zu beenden. In der Docker-Compose das DB-Image von dem MySQL-Image auf das MariaDB-Image zu ändern und noch mal die Container neu zustarten und ein wieder install durchführen.
Dann sollte alles laufen und man kann sich unter localhost:8000/admin mit admin - shopware anmelden.
Wenn man die lokalen psh.phar-Aufrufe durch die direkten Docker-Befehle ersetzt, sollte es auch unter Windows funktionieren. Innerhalb des Containers kann man natürlich wieder psh.phar verwenden.
Update: manchaml kann auch helfen, dieses vorher einmal auszuführen, bevor man den Container startet und dort install aufruft:
Irgendwann fängt man an aus seinem großen Framework einzelne kleine Module heraus lösen zu wollen. Die will man dann als Composer-Requirements wieder einbinden. Zum Glück geht das sehr einfach, indem man einfach ein Repository zu seiner composer.json hinzufügt:
Man kann nicht nur über die composer.json den Autoloader befüllen. Wenn man z.B. Module hat die nicht über den Composer installiert werden sondern aus einem Verzeichnis geladen werden, müsste man die Einträge per Hand vornehmen, was aber nicht wirklich ideal ist.
Zum 10. Geburtstag meines PHP-Frameworks wird sich da viel ändern und es damit dann wieder etwas mehr zu anderen Frameworks aufschließen können.
Mein eigener Class-Loader fliegt raus und es wird noch der ClassLoader vom Composer verwendet. Meiner kann zwar auch mit PSR4 umgehen, aber nach dem Umstieg muss ich dann auch alles darauf umstellen und habe keine Ausrede mehr, weil die Kompatibilität weg fällt.
Es gibt nun ein public-Verzeichnis so dass alle Config-Dateien und Classes außerhalb des Bereiches liegen, auf dem Benutzer zugreifen können. Das sorgt für mehr Sicherheit, macht das Laden von CSS und Bildern aus dem Theme-Verzeichnis aber komplizierter. Ich überlege hier auf Assetic umzusteigen. Momentan läuft meine Lösung aber sehr gut.
Und das Beste und wichtigste was aber auch am meisten Arbeit machen wird (darum habe ich ganz viele alte Module erst einmal gelöscht und lasse auch die alten PHP-Pages drin) ist, dass Module-Pages nun wirklich mit Controller und Twig-Template gerendert werden. Die Twig-Templates könenn vom Theme und von eigenes Templates in der Instance überschrieben werden und so kann man nun endlich das Aussehen der Module leicht und schnell anpassen.
Smarty war schon länger drin, wurde aber nie benutzt und ist jetzt raus geflogen.
Mein erstes Projekt damit wird sein, die Zeiterfassung für Kunden-Projekte neu zu schreiben und für alle brauchbar zu machen. Das wird wohl am Ende nur 1-2 Tage dauern. Also nichts im Vergleich zum Umbau des Frameworks.
Blog-entries by search-pattern/Tags:
Möchtest Du AdSense-Werbung erlauben und mir damit helfen die laufenden Kosten des Blogs tragen zu können?