Blog: Latest Entries (15):


Shopware: Quelloffene Plugins im Store

Quelloffene Plugins sind toll. IonCube ist doof, umständlich und schwer einzurichten. Wenn es die Möglichkeit gibt würde ich ein quelloffenes Plugin immer vorziehen.
Dieser Artikel von Shopware fasst alles sehr gut zusammen.

Viele Fragen zu einem Shopware-Plugin können einfacher und schneller durch einen Blick in den Code beantwortet werden:

- Wo holt es sich die Daten her?
- Wo schreibt es die Daten hin?
- Welche Daten müssen vorhanden sein, damit alles verarbeitet werden kann?
- Wann wird welche Funktion aus geführt?

Und gerade die Angst, der Code könnte geklaut werden halte ich in 99,99999% für eine verzerrte Sicht der Dinge. Denn man muss einfach davon ausgehen, dass die Plugins aus genau zwei Gründen gekauft werden:

- Der Betreiber des Shops kann nicht Programmieren und hat auch keine Entwickler
- Das Plugin selbst zu entwickeln wäre teurer als es zu kaufen

Ich selbst habe ein paar Plugins im Store die auch wirklich wenigen Zeilen Code bestehen. Manche manipulieren genau einen Wert im Request. Es hat etwas gedauert bis man musste welcher Wert manipuliert werden muss (das weiß man, weil man ja den Quellcode von Shopware einsehen kann). Umsetzen, Testen, verbessern, etc. Aber keine großen oder komplexen Leistungen.

Warum habe ich diese quelloffen im Store? Weil ich glaube, dass ein Entwickler (wenn er gerade keinen Forschungsdrang hat) eher mal paar Euro ausgibt als selbst es nach zubauen und alles selbst nochmal testen und überprüfen zu müssen.

Lösungen zu verheimlichen ist nie gut. Weil man selbst braucht ja auch oft mal Hilfe oder Denkanstöße. Mit genug Zeit kommt jeder auf die Lösung, aber man hat immer genug zu tun, um dankbar dafür zu sein, dass jemand anderes sich diese Zeit genommen hat und man sich mit deren Dingen beschäftigen kann.

Der neue Shopware-Newsletter

Mir gefällt der neue Shopware-Newsletter nicht. OK er ist übersichtlicher, aber mir gefällt es nicht, dass die neuen und aktualisierten Updates nicht mehr direkt als Liste enthalten sind sondern nur noch Banner-Links auf deren Store, wo man diese Plugins findet.

Mir gefiel es immer meinen Namen dort zu lesen. Hat den Freitag oft verschönert :-)

Shopware: Probleme mit value in der config.xml

Ich hatte ein kleines Problem mit der config.xml, dass sich rein auf die Reihenfolge der XML-Nodes bezog.

Richtig:

<element required="true" type="text" scope="locale">
<name>default_value</name>
<label lang="de">Standard Wert</label>
<label lang="en">Default value</label>
<value>default</value>
</element>


Falsch:

<element required="true" type="text" scope="locale">
<name>default_value</name>
<value>default</value>
<label lang="de">Standard Wert</label>
<label lang="en">Default value</label>
</element>


Muss man nur wissen....


If Empty mit XPath

Wenn in einem Node kein Text ist, soll der Text eines anderen Nodes verwendet werden.


/ITEM/TEXT_SHORT[text()]/text() | /ITEM/TEXT_LONG[text() and not(/ITEM/TEXT_SHORT[text()])]/text()


Hier wird vorrangig der TEXT_SHORT verwendet. Sollte dieser aber leer sein, wird auf den TEXT_LONG zurück gegriffen.
Ich habe mir das auch aus anderen Beispielen so lange hin und her gebastelt bis es ging. Aber so erspart man sich zusätzlichen Code der später die beiden Texte abgleicht und es wird gleich richtig eingelesen.

Shopware: Properties und deren Klassen bei der Suche

Wenn man sich mal etwas im SearchBundle von Shopware rumtreibt und dann selbst mit Doctrine die Property-Klassen aus dem SerachBundle auf die realen doctrine Models/Entities mappen möchte, sollte man beachten:


SearchBundle: Set
Doctrine: Group

SearchBundle: Group
Doctrine: Option

SearchBundle: Option
Doctrine: Value


bbcode-image


Konsistenz mag dahinter stecken, aber ich kann sie nicht erkennen.

Also kann etwas so aussehen:


/** @var Shopware\Models\PropertyGroup $group */
$group = Shopware()->Models()->find(Shopware\Models\PropertyGroup::class, $setSearchBundle->getId());

Bootstrap Pointer-Cursor

Wenn man mit Bootstrap eine Oberfläche baut und auf einem nicht Link gerne den Pointer als Cursor hätte, gibt es da eine einfache Lösung:


<li role="button" ng-click="doSomething()">Blubb</li>


Ob sich die Entwickler von Bootstrap die Verwendung so gedacht haben, kann ich nicht sagen, aber es funktioniert.

LAMP in 3 Zeilen

Mehr braucht man nicht um mit Ubuntu ein LAMP-System einzurichten. Danach kann man direkt seine conf in sites-available anlegen und loslegen.


sudo apt-get install apache2 libapache2-mod-php7.1 php7.1 php7.1-mysql mysql-server openssh-server
sudo apt-get install phpmyadmin
sudo a2enmod rewrite


Bei der phpmyadmin Installation nicht vergessen nochmal Apache wirklich mit Space auszuwählen, es ist nur markiert aber nicht ausgewählt.

phpmyadmin ist optional Java und Oracle SQL-Developer oder einfach die MySQL Workbench würden auch gehen.

POS-Projekt Demo

Ein erster Eindruck von meinem neuen Projekt. Ein POS-Plugin für Shopware, wie man es in Diskos oder Restaurants wie Vapiano nutzen kann.

bbcode-image

bbcode-image

bbcode-image

bbcode-image

bbcode-image

bbcode-image




Das Plugin entsteht für einen Auftraggeber und wird wohl erst einmal nicht frei im Store verfügbar sein.

Jetzt müssen Demo-Daten gebastelt werden.

Shopware: Meine Standard Apache Config

Meine Apache-Conf für Shopware-Installationen, die ich in verschiedenen VMs verwende.


<VirtualHost *:80>
ServerAdmin hp@ubuntu.local
DocumentRoot "/var/www/shopware"
ServerName shopware.localhost
ServerAlias www.shopware.localhost
ErrorLog "/var/log/apache2/shopware.error.log"
CustomLog "/var/log/apache2/shopware.access.log" combined

RewriteEngine On
RewriteMap lc int:tolower

<Directory "/var/www/shopware">
Options Indexes FollowSymlinks MultiViews
AllowOverride All
Order allow,deny
Allow from all
</Directory>
</VirtualHost>


Alt vs Neu und Modern ... aber es funktioniert doch

Manchmal komme ich mir alt und unflexibel vor. Ich benutze zum Bauen von allen möglichen Dingen Ant und wenn es um Dependecy-Management geht nutze ich Maven und den Composer.
Diese ganzen neuen und modernen Build-Systeme habe ich war genommen, aber irgendwie habe ich da nicht die Zeit und Energie mich jetzt mit jedem auseinander zu setzen und die Vorteile, Nachteile und Unterschiedene genau zu analysieren. Am Ende soll es ja doch nur das machen, was mein momentanes System schon macht. Gradle sieht sehr schön und übersichtlich auch.. aber selbst Maven sieht in den einfachen Setup übersichtlich und einfach aus.

Wenn ich also mein Shopware-Plugin baue, was bringt es mir mein universales Ant-Script (das ich nur reinkopieren muss bei jedem neuen Plugin) durch etwas "moderneres" zu ersetzen.
Das Ergebnis sieht gleich aus, wird sicher nicht merklich schneller sein und ich muss keine seltsamen/komplexen Dinge über Variablen und so tun, um zum Ziel zu kommen.

Ist das schlecht? Ist es nachvollziehbar? Ich weiß es nicht... aber ich glaube ich sollte mal wieder mich mehr mit neuen Dingen beschäftigen. Einfach mal wieder etwas Forschung, wenigstens um es alles mal gesehen zu haben. Das gilt besonders für Angular >2 auch wenn ich AngularJS weiterhin wirklich toll finde und es mir vollkommen für meine Aufgaben reicht (und ich es ExtJS wohl immer vorziehen werde, wo es nur geht.) .. und Symfony 4 steht auch noch auf meiner Liste.

QNAP NAS und IP-Kamera

Nach einigen Versuchen mit einem billigen China NAS (langsam und laut), der NAS-Funktion der Fritzbox (die plötzlich die externe SSD nicht mehr erkannte) bin ich nun bei einer gebrauchten QNAP TS-120 gelandet. Eine der Hauptaufgaben des NAS sollte es ja sein Bilder und Videos einer oder mehrere Überwachungskameras zu speichern. Zusätzlich sollte es auch für andere Dinge dienen, wie Datenaustausch zwischen den PCs und so.

Die TS-120 kann viele Dinge der größeren und neueren NAS nicht. So kann sie weder als VM-Host dienen noch als Domain-Controller in Windows-Netzwerken eingesetzt werden (was schön gewesen wäre). Aber trotzdem ist sie den anderen Lösungen, die ich hatte, weit überlegen.

Die Einrichtung der IP-Kamera ging auch entsprechend einfach. Sie speichert über FTP und man kann über SMB dann auf die Daten zugreifen.

bbcode-image


bbcode-image


bbcode-image


bbcode-image


bbcode-image

Shopware: Steuerfreiheit und USt-IdNr

Wer sich schon mal bei Shopware damit auseinander setzen musste, wie die Einstellung "Deaktiviere Steuern wenn eine USt-IdNr. angegeben wurde" funktioniert, ist sicher schnell im Checkout-Controller und in der Methode isTaxFreeDelivery($userData) gelandet.
Leider ist diese Methode in einem Stil geschrieben, der sie meiner Meinung nach extrem schwer lesbar macht. Die wieder negierten emptys und vielen return sorgen dafür, dass man den dahinter steckten logischen Ausdruck nur schwer erkennt, wobei der an sich ziemlich einfach ist.
Alles ist wie man man erwartet nur das bei fehlender VatID in der Shipping-Address auch die Billing-Address "einspringen" kann, muss man sich mehrmals durch den Kopf gehen lassen.

Ich habe die Methode noch mal in für mich besser lesbarer Form nieder geschrieben:


$shippingCountryTaxFree = !empty($userData['additional']['countryShipping']['taxfree']);
$shippingCountryTaxFreeVatID = !empty($userData['additional']['countryShipping']['taxfree_ustid']);
$billingCountryTaxFreeVatID = !empty($userData['additional']['country']['taxfree_ustid']);

$shippingVatID = !empty($userData['shippingaddress']['ustid'];
$billingVatID = !empty($userData['billingaddress']['ustid'];

return $shippingCountryTaxFree
||
($shippingCountryTaxFreeVatID &&
(
(!$shippingVatID && billingVatID && billingCountryTaxFreeVatID)
||
$shippingVatID
)
);


Die Logik stammt aus der Version 5.3.5

Shopware: Batch-Params

So sehen die Params von einem Article-Batch (3 Artikel) für die Article-API aus:


{
"id": false,
"subId": false,
"version": 1,
"useNumberAsId": "true",
"module": "api",
"controller": "articles",
"action": "index",
"0": {

},
"1": {

},
"2": {

}
}


Int-Index und selbst ein Array, dadurch ist ein einzelner Artikel darin zu erkennen. Id gibt es in den Params direkt auch noch, also ist das kein Indikator für eine Batch-Request.

Older posts: