Magento Attribute effizient inkrementieren & dekrementieren

Magento.SE Screenshot

Diese Frage tauchte auf Magento StackExchange auf:

I need to decrement a value with an atomic database operation, is it possible using Magento models?

Es ist tatsächlich möglich, Attribute mit einem Update zu inkrementieren und dekrementieren und zwar mit einer weniger bekannten Technik mittels Zend_Db_Expr. Ich teile es auch hier:

$object->setNumber(new Zend_Db_Expr('number-1'));

Als Referenz:

Die Methode Mage_Core_Model_Resource_Abstract::_prepareDataForSave() enthält folgenden Code:

if ($object->hasData($field)) {
    $fieldValue = $object->getData($field);
    if ($fieldValue instanceof Zend_Db_Expr) {
        $data[$field] = $fieldValue;
    } else {
        ... [normale Verarbeitung folgt]

EAV Models:

Beachte, dass man das Attribut nur mit seinem Namen referenzieren kann (“number” im Beispiel) wenn es eine echte Spalte der Haupt-Tabelle ist, kein EAV-Attribut.

Obwohl die obengenannte Methode nur von Models mit flachen Tabellen benutzt wird, kann Zend_Db_Expr aber auch für EAV Attribute benutzt werden, die Methode die den Parameter verarbeitet, ist Varien_Db_Adapter_Pdo_Mysql::prepareColumnValue().

ABER man muss dann immer den Spaltennamen “value” verwenden:

$product->setNumber(new Zend_Db_Expr('value-1'));

Es ist nicht notwendig, einen Alias für die Tabelle anzugeben, weil jedes Attribue einzeln mit eigenem Query verarbeitet wird, so dass “value” nicht mehrdeutig ist.

Spryker vs. Magento

Neulich hatte ich die Gelegenheit, einen Blick in den Source Code von Spryker zu werfen, dem Ecommerce-Framework das sich anschickt zum neuen Player im Enterprise-Bereich zu sein. Spryker wird vom Berliner Inkubator Project A für den Einsatz in selbst geförderten Unternehmen entwickelt und soll in diesem Jahr der Öffentlichkeit zugänglich gemacht werden. Wobei Öffentlichkeit nicht ganz stimmt, denn soviel vorab: Eine Open Source Version ist nicht geplant, Lizenzen sollen um 100.000 € / Jahr kosten. Agenturen können sich als Partner registrieren, um ohne Lizenz Zugriff auf Source Code und Dokumentation zu bekommen. Mit der ersten verkauften Lizenz gibt es Zugriff auf zusätzliches Training-Material. Freelancer werden nicht angesprochen. Bereits offiziell als Partner gelistet sind auch die im deutschen Magento-Umfeld bekannten Agenturen CommercePlus und Symmetrics.

Was ist das Besondere an Spryker?

Spryker versteht sich nicht als fertig einsetzbares Produkt, sondern als Framework das alle Bausteine für eine individuelle E-Commerce Lösung bereitstellt, aus denen man sich für sein Projekt die benötigten auswählt und erweitert. Damit wird die Realität berücksichtigt, dass kein Projekt wie das andere ist und jeder Shop seine eigenen Prozesse und Infrastruktur hat, auf die individuell eingegangen werden muss.

Der Kern von Sprkyer sind zwei eigenständige Applikationen, Yves und Zed. Kurz gefasst, ist Yves eine leichtgewichtige Anwendung für das Frontend, Zed das schwere Geschütz fürs Backend.

Discover Spryker
Bild: http://spryker.com/product/

Yves (in der ersten Version mit Yii programmiert, jetzt mit Silex) liest sämtliche benötigten Daten ausschließlich aus einem In-Memory NoSQL Backend wie Redis.
Zed (Zend Framework 2) übernimmt die Kommunikation mit MySQL, Message Queue und Dritt-Systemen und enthält die Geschäftslogik zu Bestellprozessen usw.
Continue reading “Spryker vs. Magento”

Magento: Direktlink auf Tab in Adminhtml Tab Widgets

Für eine Extension an der ich neulich gearbeitet habe, habe ich mich gefragt, ob es eine eingebaute Möglichkeit gibt, direkt auf einen Tab einer Seite im Backend zu linken. Meine Nachforschungen haben nichts ergeben (sprich: Mein Google Foo hat versagt), also habe ich mir den Core Code vorgenommen um einen Ansatz zu finden. Was ich herausgefunden habe:

Das Problem

Im speziellen wollte ich einen Link auf den “Bezeichnungen / Optionen verwalten” Tab der “Produktattribut bearbeiten” Seite setzen:

Screenshot

Die Lösung

Tatsächlich ist es mit einem URL-Parameter möglich: ?active_tab=$id.

Wie finde ich die Tab-ID heraus?

Finde den verantwortlichen Tab Container. Dies ist eine Unterklasse von Mage_Adminhtml_Block_Widget_Tabs, in meinem Fall Mage_Adminhtml_Block_Catalog_Product_Attribute_Edit_Tabs.

Du wirst Aufrufe von $this->addTab() finden, üblicherweise in den Methoden _beforeToHtml(), oder _construct(). Der erste Parameter von addTab() ist die Tab ID:

    $this->addTab('labels', array(
        'label'     => Mage::helper('catalog')->__('Manage Label / Options'),
        'title'     => Mage::helper('catalog')->__('Manage Label / Options'),
        'content'   => $this->getLayout()->createBlock('adminhtml/catalog_product_attribute_edit_tab_options')->toHtml(),
    ));

Die URL ist also /admin/catalog_product_attribute/edit/attribute_id/123/?active_tab=labels, generiert mit diesem Code (innerhalb eines Adminhtml Blocks):

    $this->getUrl('adminhtml/catalog_product_attribute/edit',
        array('attribute_id' => 123, '_query' => array('active_tab' => 'labels'));

Wie es funktioniert

Schauen wir uns den verantwortlichen Code an:
Continue reading “Magento: Direktlink auf Tab in Adminhtml Tab Widgets”

Magento ACL: Kein “Ausloggen und wieder einloggen” mehr nach Extension-Installation

In fast jeden Installationsanweisungen für Magento Extensions findet man den Schritt “Ausloggen und wieder einloggen”, der notwendig ist um Zugriff auf neue Bereiche im Admin Menü oder der Systemkonfiguration zu erhalten. Aber warum müssen wir das hinnehmen? Das Problem ist, dass die Access Control List (ACL) nur bei Login geladen wird und dann in der Session gecached bleibt. Sie bei jedem Zugriff zu laden ist keine brauchbare Alternative, das würde das Backend zu sehr verlangsamen.

Aber mit nur wenigen Zeilen Code können wir das Neuladen der ACL ein wenig komfortabler gestalten:

Der Code

Diese Controller Action lädt die ACL auf Anfrage neu:

class SSE_AclReload_Adminhtml_Permissions_AclReloadController
    extends Mage_Adminhtml_Controller_Action
{
    public function indexAction()
    {
        $session = Mage::getSingleton('admin/session');
        $session->setAcl(Mage::getResourceModel('admin/acl')->loadAcl());

        Mage::getSingleton('adminhtml/session')->addSuccess(
            $this->__('ACL reloaded'));
        $this->_redirectReferer();
    }
}

Dieses Template stellt einen Button zur Verfügung, der zu dem neuen Controller linkt:

<?php
$request = Mage::app()->getRequest();
?>
<a href="<?php echo $this->getUrl('adminhtml/permissions_aclReload/index'); ?>">
<?php echo $this->__('Reload ACL'); ?>
</a>

Und dieses Layout Update fügt den Button zu “404” Fehlerseiten im Backend hinzu (die, die man sieht, wenn man keinen Zugriff auf eine Seite hat):

    <adminhtml_noroute>
        <reference name="content">
            <block type="adminhtml/template" name="content.aclReload"
                after="content.noRoute" template="sse_aclreload/button.phtml" />
        </reference>
    </adminhtml_noroute>

Das Ergebnis

Screenshot Magento Admin 404

Continue reading “Magento ACL: Kein “Ausloggen und wieder einloggen” mehr nach Extension-Installation”

TranslationHints 0.2 für Magento veröffentlicht

Screenshot: Translation Hint

Ich habe Version 0.2 meiner Magento Extension SSE_TranslationHints veröffentlicht, einem Entwickler-Werkzeug, das die Quelle von Übersetzungen zusammen mit alternativen, überschriebenen Übersetzungen für den selben Text direkt im Frontend anzeigt.

Die Konfiguration ist wie gehabt analog zu den Template Hints:

Screenshots: Translation Hints Configuration

News

Zusammen mit der Quelle der Übersetzung sieht man jetzt auch alternative Übersetzungen, die von der genutzten Quelle überschrieben wurden und einige zusätzliche Informationen.

Im folgendem Beispiel sieht man den Geltungsbereich (Scope) der Übersetzung (Mage_Customer), die Übersetzung für diesen Scope, sowie die Übersetzung, die im globalen Scope verwendet würde, das heißt wenn es keine Scope-spezifische Übersetzung gäbe. Der CACHED Tag sagt uns, dass die Übersetzungen us dem Translation Cache geladen wurden:

Screenshot: Translation Hint

Continue reading “TranslationHints 0.2 für Magento veröffentlicht”

Magento: Block-Inhalt verschwindet nach core_block_to_html_after Event

Vorsicht mit Mage_Core_Block_Abstract::toHtml() innerhalb eines Observers für core_block_to_html_after! Ich habe die Methode genutzt, um HTML aus einem Block in einen existierenden Block zu injizieren, mit dem Ergebnis dass alles außer diesem neuen Block von der Ausgabe entfernt wurde.

Beim Debugging im Core habe ich die Ursache darin gefunden, wie das Event dispatched wird:

        /**
         * Use single transport object instance for all blocks
         */
        if (self::$_transportObject === null) {
            self::$_transportObject = new Varien_Object;
        }
        self::$_transportObject->setHtml($html);
        Mage::dispatchEvent('core_block_abstract_to_html_after',
            array('block' => $this, 'transport' => self::$_transportObject));
        $html = self::$_transportObject->getHtml();

Wie man sieht, ist das Transport-Objekt, das genutzt wird um Änderungen am HTML in Observern zu ermöglichen, eine Klassenvariable von Mage_Core_Block_Abstract, und verhält sich ähnlich wie ein Singleton. Ich kann mir keinen guten Grund dafür denken aber es riecht verdächtig nach premature optimization.

Was nun passiert ist, dass während das Event verarbeitet wird, der neue Block seine eigene Ausgabe in seinem eigenen toHtml() Aufruf dem selben Transport-Objekt zuweist und die ursprüngliche Ausgabe verloren geht, wenn man sie nicht vorher gesichert hat.

Die Lösung für mein konkretes Problem war, den Block an anderer Stelle zu erstellen und vorzurendern, aber wenn das nicht getan wird, muss die Ausgabe direkt zu Beginn im Observer in eine neue Variable kopiert werden:

$html = $observer->getTransport()->getHtml(); // should be the first statement

// now you can do what you want, create other blocks, modifiy $html ...

$observer->getTransport()->setHtml($html); // should be the last statement

Magento-Entwicklung mit Vagrant – Teil 4: Puppet – Provisioning für Fortgeschrittene

Wie in den vorigen Teilen der Serie angedeutet, ist der nächste Schritt, ein Provisionierungs-Tool zu nutzen, also ein Tool zur Automatisierung von Infrastruktur, mit dem z.B. Entwicklungs-, Test- und Produktiv-Umgebungen synchron konfiguriert werden können. Dieses ersetzt weitestgehend die Shell-Skripte zur Einrichtung der VM durch eine deklarative Sprache zur Definition des gewünschten Zustands der Systeme. Dieser Unterschied ist entscheidend: wir definieren nicht länger eine Abfolge von Befehlen (also, WIE der Zustand erreicht werden soll), sondern den Zustand selbst, und Puppet kümmert sich um die jeweils notwendige Ausführung.

Populäre Alternativen zu Puppet sind Chef und Ansible (beide in Python geschrieben). Ich habe mich für Puppet entschieden, aus folgenden Gründen:

  1. es läuft auf Ruby, genau wie Vagrant, also eine zusätzliche Technologie weniger
  2. es ist für alle gängigen Plattformen verfügbar, läuft also auch unter Windows
  3. das GUI Tool PuPHPet ermöglicht das Konfigurieren von Vagrant Boxen für PHP Anwendungen (und mittlerweile auch Ruby, Python, NodeJS) in kürzester Zeit und ohne die Syntax der Puppet DSL kennen zu müssen.

Use PuPHPet for Magento

Weiterlesen auf integer-net.de

Magento Tutorial: Wie man Increment Models nutzt, um IDs zu generieren (oder SKUs)

Hast du dich je gefragt, wie Magento die increment_id Werte für Bestellungen, Rechnungen etc. generiert und wie man diesen Mechnismus nutzen oder erweitern kann? Vielleicht hast du die eav_entity_store Tabelle entdeckt, die die jeweils letzte increment id pro Entity-Typ und Store enthält, wobei je Store ggf. ein unterschiedlicher Präfix verwendet wird:

mysql> select * from eav_entity_store;
+-----------------+----------------+----------+------------------+-------------------+
| entity_store_id | entity_type_id | store_id | increment_prefix | increment_last_id |
+-----------------+----------------+----------+------------------+-------------------+
|               1 |              5 |        1 | 1                | 100000090         |
|               2 |              6 |        1 | 1                | 100000050         |
|               3 |              8 |        1 | 1                | 100000027         |
|               4 |              7 |        1 | 1                | 100000005         |
|               5 |              1 |        0 | 0                | 000000011         |
|               6 |              5 |        2 | 2                | 200000001         |
|               7 |              5 |        3 | 3                | 300000002         |
|               8 |              8 |        3 | 3                | 300000001         |
|               9 |              6 |        3 | 3                | 300000001         |
+-----------------+----------------+----------+------------------+-------------------+
9 rows in set (0.00 sec)

In diesem Artikel erkläre ich, wie dieses System für andere Entities genutzt werden kann.

Zunächst mal, die Standard-Methode funktioniert nur mit EAV Entities, nur mit einem Attribut pro Entity und dessen Name muss increment_id sein. Ich erkläre gleich aber noch, wie diese Beschränkungen umgangen werden können.

Continue reading “Magento Tutorial: Wie man Increment Models nutzt, um IDs zu generieren (oder SKUs)”

Mage Unconference 2015 – 7.-8. März – Berlin

Mage Unconference 2015

Vom 7. bis 8. März veranstaltet FireGento die erste Mage Unconference für Kunden, Händler, Anbieter, Agenturen, Provider – und natürlich – auch Entwickler. Der Inhalt der Unconference wird ganz alleine von Dir und den anderen Teilnehmern festgelegt.

>>> Mach mit und sei Teil der Community vom 7. bis 8. März 2015 in Berlin! <<<

Ich bin dabei und hoffe auf regen Austausch. Wer Interesse hat, sollte nicht zu lange zögern, bevor die Veranstaltung wegen zu weniger verkaufter Tickets abgeblasen wird!

Magento-Entwicklung mit Vagrant – Teil 3: Projektstrukturen für Magento

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).

Weiterlesen auf integer-net.de