Blog: Latest Entries (15):


Kurz und Knapp: Einkaufswelten

Was mich stört:

- sehr kleine Ansicht des TinyMCE und keine gute Code-Ansicht (wie Codemirror oder so)
- Bilder werden immer mit festen Pixelwerten skaliert
- Es kommen CSS-Klassen hinein die man nicht will
- IMG sind z.B. immer Block-Elemente und nicht inline wie man es erwarten würde und dann geht einfache "text-align:center;" nicht
- Das Handling von ausgeblendeten Elementen ist nicht wirklich gut
- Das Scaling-Verhalten der Banner lässt sich nicht konfigurieren
- Direkte Rahmenstyles für die Boxen wäre toll
- kein Undo
- Ein Grid wie in Bootstrap mit automatischer Anpassung an die Bildschirmbreiten fehlt, auch wenn die vorhandene Lösung schon ganz ok ist
- Im- und Export von Einkaufswelten kommt erst mit 5.3
- Am Ende muss man doch relativ oft an den HTML-Code und CSS-Klassen und so anpassen

bbcode-image


Aber man muss am Ende doch nochmal sagen.. für mich ist es die Beste Lösung, die es momentan gibt und auch durchaus von Leuten bedienbar ist, die wenig mit HTML und WebDesign zu tun haben.

Shopware Artikel Modus und die Magicnumbers 0, 1, 2, 3 und 4

Wenn man mit dem sBasket von Shopware zutun hat und auch mal selbst was in den Basket legen möchte und dann vielleicht ist das was man rein tun möchte kein standard Artikel sondern ein Rabat oder ähnliches, kommt man schnell zu dem Feld Modus/Mode.

Um die Magicnumbers zu decodieren muss man etwas tiefer suchen.. in der cart_item.tpl.. wäre jeder sofort drauf gekommen.. oder?


{* Constants for the different basket item types *}
{$IS_PRODUCT = 0}
{$IS_PREMIUM_PRODUCT = 1}
{$IS_VOUCHER = 2}
{$IS_REBATE = 3}
{$IS_SURCHARGE_DISCOUNT = 4}


Gutscheine findet man also dann bei Einträgen mit dem Mode 2. Gerade bei Exports von Bestellungen für externe Systeme kann dieser Mode sehr praktisch sein.

Die Einträge mit der 3 werden bei jedem Anzeigen neu aufgebaut und somit werden Positionen, die man einfach in die DB schreibt auch sofort wieder gelöscht. Für den Zweck scheint Mode 4 der richtige zu sein. Wobei ich dort noch Probleme mit dem Löschen habe, aber das kann ich sicher noch über ein Event oder Hook lösen.

Meine ersten Shopware Plugins

Morgen beginnen die Test meiner ersten beiden Shopware Plugins. Teilweise sehen sie auch wirklich wie "die ersten" aus, auch wenn ich nochmal viel nachgebessert habe. Aber gerade optisch ist noch viel Raum nach Oben. Bis Freitag kann man da sicher noch was machen, um auch optisch noch was besseres abliefern zu können.

bbcode-image


Weitere und bessere Plugins, aber erst einmal ohne Oberflächen, sondern als Unterstützung für Entwickler und Designer, folgen dann hoffentlich in den nächsten Wochen und Monaten.

Manuelle Zeitmessungen mit dem Switch GmbH Time-System

Zeitmessungen bei Rennen müssen nicht immer mit RFID gemacht werden. Man kann auch ganz einfach einen PC, ein Tablet oder ein Smartphone pro Messstation nehmen und eine Person muss nur auf die Teilnehmer-Nummer klicken/drücken, um eine Messung zu speichern.

Für die meisten Rennen im Amateurbereich ist die Genauigkeit mehr als ausreichend. Also ein vollständiger Ersatz für Stoppuhren oder andere Smartphone-Apps, die man sonst für Kontrollmessungen verwenden würde.



Und alles natürlich dann in Echtzeit auf dem Server.


Tasks der nächsten Zeit

Die nächsten Wochen und Monate werden sehr stressig. Meine Pläne sind:

- Umziehen und Renovieren (vielleicht mit Blog-Post über Netzwerk, Server und Überwachungskameras)
- Ein einfaches Shopware Plugin in den Community Store zu bekommen (Das Plugin ist so gut wie fertig.. jetzt kommt die Upload-Theorie* .. schlimmer als der App-Store für Firefox OS kann es sicher nicht sein)
- Einen kleinen aber etwas speziellen Shop online bringen (ich werde berichtigen wie es läuft und ob es am Ende erfolgreich war)
- Zwei Termine mit dem Switch GmbH Time-System stehen an, wo ich auch Blog-Post und so liefern werde.. mehr als letztes Jahr
- Ein Video über die manuelle Zeitmessung mit dem Time-System
- Und nach dem Umbau der letzten 3 Monate am aoop PHP-Framework mit MVC, neuer Verzeichnisstruktur, PHP 7, Namespaces, Composer-Autoloader, etc müsste ich wirklich mal eine neue Version releasen.. ich bin doch relativ stolz auf die neue Version ,weil sie doch etwas ist was man als modern bezeichnen kann

* Anleitung für den Shopware Community-Store

Shopware Forms mit Smarty und Customer-Model?

bbcode-image

Shopware: Wie Enlight_Event_EventArgs funktionieren

bbcode-image


Unser Ziel ist es den Text einer Email zu ändern die aus einer Form generiert wird. Wir nutzen dieses Event:


$mail = Shopware()->Events()->filter('Shopware_Controllers_Frontend_Forms_commitForm_Mail', $mail, ['subject' => $this]);


Wenn wir nun die Args durch gehen...


public function eventMailListener(\Enlight_Event_EventArgs $args){
foreach($args as $key => $value){
echo $key;
}
die();
}


... das nur "subject" also der Controller darin zu finden ist.

Jetzt gucken wir und mal die filter-Methode vom EventManager an.

public function filter($event, $value, $eventArgs = null)
{
if (!$this->hasListeners($event)) {
return $value;
}

$eventArgs = $this->buildEventArgs($eventArgs);
$eventArgs->setReturn($value);
$eventArgs->setName($event);
$eventArgs->setProcessed(false);

foreach ($this->getListeners($event) as $listener) {
if (null !== ($return = $listener->execute($eventArgs))) {
$eventArgs->setReturn($return);
}
}
$eventArgs->setProcessed(true);

return $eventArgs->getReturn();
}


und da sehen wir


$eventArgs->setReturn($value);


Also ist die Lösung


public function eventMailListener(\Enlight_Event_EventArgs $args){
/** @var \Enlight_Components_Mail $mail */
$mail = $args->getReturn();
echo $mail->getPlainBodyText();
die();
}


Wenn man das erst einmal verstanden hat, ist alles plötzlich ganz einfach. Ach ja, wenn man das Subject überschreiben möchte erst einmal $mail->clearSubject(); ausführen.



Cronjob für Zertifikate

Da es nicht gerade eine tolle Lösung ist, alle paar Tage die Let's Encrypt Zertifikate per Hand zu aktualisieren, sollte man sich einen Cron-Job erstellen.


Per Hand kann man hier mit alle Zertifikate aktualisieren, die bald ablaufen werden:

sudo letsencrypt renew


Den Cronjob kann auch ganz einfach anlegen.


sudo crontab -e


Und dann den Eintrag hinzufügen. Ich hab es mit vim gemacht.

Also mit den Pfeiltasten ans Ende der Datei. i drücken.


30 2 * * 1 /usr/bin/letsencrypt renew >> /var/log/le-renew.log


hinzufügen. ESC drücken und mit :w speichern und dann mit :q schließen.

Das war es auch schon.

Nach der Anleitung auf digitalocean.com

Downloads und File-Saving

Manchmal möchte man einfach eine am Server erzeugte Datei dem Benutzer zum Download anbieten. Dafür könnte man einen einfachen Link erzeugen.

Wenn die Datei aber aber auf einer größeren JSON Datenstruktur basiert, die man erst einmal mit an den Server schicken muss, ist man mit einem Link und GET-Parametern schlecht beraten.

Am liebsten würde man die Daten ganz normal per Angular an den Server senden, dann den Datei-Inhalt erhalten und den am Client für den Benutzer als Download anbieten.

Manchmal hat man auch schon alle Daten schon am Client vorliegen oder kann diese dort einfach erzeugen oder konvertieren.

Hier hilft eine Objct-URL und der Blob-Objekt von JavaScript. Damti erstellt man sich einen Link den man über ein Event auslöst und so den Klick des Benutzers auf den Link simuliert.


var funcSaveFile = function(csvData){
//create link
var url = URL.createObjectURL(new Blob([csvData]));
var a = document.createElement('a');
a.href = url;
a.download = 'file.csv';
a.target = '_blank';

//triger link with an event
var event = document.createEvent("MouseEvents");
event.initMouseEvent("click", true, true, window,
0, 0, 0, 0, 0,
false, false, false, false,
0, null);
a.dispatchEvent(event);
};


Damit lassen sich relativ einfach Daten aus einer AngularJS oder anderen JavaScript Anwendung zum lokalen Download anbieten, was man für Speichern Methoden und so etwas ja doch häufiger braucht.

Shopware REST-API Artikel speichern mit Preisen


\Shopware\Models\Article\Price by id X not found


Wenn man bei Shopware über die REST-API einen Artikel lädt und dann wieder speichern möchte, kann es dazu kommen, dass ein Fehler auftritt, dass der Preis mit der Id X unbekannt sei. Das scheint wohl so gewollt sein. Deswegen sollte man beim Mappen auf Klassen die Id des Prices aus dem mainDetail des Artikeln einfach unterlassen.


//persist failed if a id is present
@JsonIgnore
private int id = 0;


Hier findet meine Post im Shopware-Forum zu dem Thema

ORMs und Performance

Und das ist dann der Punkt an dem ich wieder anfange daran zu zweifeln, dass ORMs wirklich für mehr als load-by-id, update, insert oder delete brauchbar sind.

Gefühlt liefern ORMs bei Performance-Fällen immer nur Lösungen, die man mit nativen Queries schon von sich aus hätte und das ORM nur zusätzlichen Overhead ohne Vorteil verursacht.

bbcode-image


https://de.slideshare.net/AndreyYatsenco/doctrine-internals-unitofwork

Unerwartete Histogramm-Probleme

Histogramm: Man nimmt sich einen Wertebereich und teilt diesen in gleich große Bereich. Nun werde alle Werte in die passenden Bereich einsortiert. Am Ende erhält man normalisierte Daten die aus Bereichen und der Anzahl der in dem Bereich liegen Werte bestehen.

Dies hat bei Bar-Charts bei der Darstellung viele Vorteile. Für Slider braucht man so etwas nicht, da man dort nur den Min- und Max-Wert braucht.

Wenn man nun viele dicht bei einander liegende Werte hat, bekommt man ein geringere Datenmenge als es die Einzelwerte wären.

Als Beispiel nehmen wir diese Werte


105
107
115
115
116
121
144


Wenn wir nun Bereiche mit der Weite von 10 definieren erhalten wir


100:2
110:3
120:1
130:0
140:1


Die Berechnung für die Normalisierung ist sehr ein einfach und daher auch schnell.

Wir sparen an der Datenmenge, je mehr Werte pro Bucket einsortiert werden können. Zusätzliche Daten entstehen aber dann wenn man leere Buckets hat. Hätten wir noch zusätzlich die Werte 1 und 1.000.000 hätten wir nicht mehr 5 Buckets sondern 1.000.000 / 10 also 100.000 Buckets für 9 Werte.

Würden wir PHP mit einer Max-Size 64M für ein Script können wir schon schnell Probleme mit dem Speicher bekommen, wenn zur Speicherung der Bucket Objekte oder eine HashMap verwendet wird.

bbcode-image


Wenn man Histogramme verwendet sollte man immer an diese Problematik denken und wenn möglich nur gefüllte Buckets laden, also ein Min-Count von 1 setzen
und die leeren Buckets erst bei Bedarf rekonstruieren.

CMS und Pages mit selben Layout

Gehen wir mal davon aus wir erstellen eine Homepage für eine Restaurant-Kette mit 3 Restaurants. Die Seite soll so gebaut sein, dass Mitarbeiter der Restaurants einfache Datenänderungen vornehmen können, ohne dafür um Hilfe fragen zu müssen. Auch sollen Änderungen im Layout einfach und schnell möglich sein, dass aber nicht durch die Mitarbeiter, da diese wohl kein HTML beherrschen.

Jedes Restaurant hat eine eigene Unterseite, die vom Aufbau aber immer gleich sind.

Das Problem ist, dass wenn es Änderungen im Layout dieser 3 Seiten geben soll, müssen die Änderungen auch in allen 3 Seiten getätigt werden. Ein einfaches Kopieren geht natürlich nicht, da man sonst ja die individuellen Texte und Bilder überschreiben würde. Die speziellen Öffnungszeiten für Feiertage einzutragen ist nicht ganz so kompliziert, wenn man einen WYSIWYG-Editor hat. Aber einfacher wäre es natürlich, wenn diese Angaben atomar eingegeben werden können und so auch nicht die Gefahr besteht, durch Fehler die gesamte Seite durcheinander zu bringen.

Ich habe für mein Framework/CMS diese Lösung entwickelt. In dem Code der Seite sind Platzhalter eingebaut, die heraus geparst werden und mit individuellen Werten gefüllt werden können. Daher kann man einfach eine vorhandene Seite kopieren und muss nur die im Formular ausgewiesenen Platzhalter neu füllen. Das Layout zu Ändern geht auch einfach weil man den Code wirklich mit Copy und Paste in alle Seiten übernehmen kann, ohne Werte zu überschreiben.

bbcode-image


bbcode-image


Man hätte natürlich auch Entitäten und Controller mit Templates bauen können. Aber für solche Zwecke ist das oft vom Aufwand her nicht gerechtfertigt, weil die verwendete Zeit nicht entsprechend bezahlt werden würde und mit dieser Lösung es wohl auch schneller geht.

bbcode-image


Und für die einfachen Benutzer ist es so auch viel übersichtlicher und sie können dann bestimmt mehr alleine Ändern, weil sie nicht der Content der gesamten Seite erschlägt.

bbcode-image

Older posts: