Was tun bei einer “Integrity constraint violation”?

Veröffentlicht am 20.09.2011 von jkuensebeck in der Schublade Anderes | Tags: , , | Comments Off

Ihr habt Mist gebaut und die Indexe werden nicht mehr richtig aufgebaut: Beim reindexieren der Indexe “catalog_product_attribute” oder “cataloginventory_stock” landet nur der Fehler
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '18263-1-1' for key 1'
im Log.
Dann habt ihr wahrscheinlich doppelte Attributewerte in den Produkten, also hat z.B. das Produkt mit der ID 16 für das Attribut “Status” (im Beispiel mit der ID 272) gleich zweimal im selben Store (mit der ID 0) einen Wert gespeichert. In der Datenbank sähe das z.B so aus:

SELECT * FROM catalog_product_entity_int LIMIT 2;
+----------+----------------+--------------+----------+-----------+-------+
| value_id | entity_type_id | attribute_id | store_id | entity_id | value |
+----------+----------------+--------------+----------+-----------+-------+
|        1 |             10 |          272 |        0 |        16 |     0 |
|        2 |             10 |          272 |        0 |        16 |     1 |
+----------+----------------+--------------+----------+-----------+-------+

Das Attribut mit der ID 272 ist also für das Produkt doppelt belegt, einmal mit dem Wert 0 und einmal mit dem Wert 1 (man hat aber auch das selbe Problem, wenn die Werte gleich sind).

Um die problematischen Werte zu finden, helfen folgende SQL Zeilen um Duplikate in den catalog_product_entity_… Tabellen zu finden:

SELECT eav_table.* FROM catalog_product_entity_int AS eav_table GROUP BY entity_id, attribute_id, store_id HAVING COUNT(*) > 1;
SELECT eav_table.* FROM catalog_product_entity_varchar AS eav_table GROUP BY entity_id, attribute_id, store_id HAVING COUNT(*) > 1;
SELECT eav_table.* FROM catalog_product_entity_text AS eav_table GROUP BY entity_id, attribute_id, store_id HAVING COUNT(*) > 1;
SELECT eav_table.* FROM catalog_product_entity_datetime AS eav_table GROUP BY entity_id, attribute_id, store_id HAVING COUNT(*) > 1;
SELECT eav_table.* FROM catalog_product_entity_decimal AS eav_table GROUP BY entity_id, attribute_id, store_id HAVING COUNT(*) > 1;

Um dann die doppelten Werte zu löschen (vorher bitte unbedingt anschauen, was doppelt ist und ob es Widerspüchlichkeiten gibt):

DELETE FROM catalog_product_entity_int WHERE value_id IN (SELECT value_id FROM (SELECT value_id FROM catalog_product_entity_int GROUP BY entity_id, attribute_id, store_id HAVING COUNT(*) > 1) AS temp);
DELETE FROM catalog_product_entity_varchar WHERE value_id IN (SELECT value_id FROM (SELECT value_id FROM catalog_product_entity_varchar GROUP BY entity_id, attribute_id, store_id HAVING COUNT(*) > 1) AS temp);
DELETE FROM catalog_product_entity_text WHERE value_id IN (SELECT value_id FROM (SELECT value_id FROM catalog_product_entity_text GROUP BY entity_id, attribute_id, store_id HAVING COUNT(*) > 1) AS temp);
DELETE FROM catalog_product_entity_datetime WHERE value_id IN (SELECT value_id FROM (SELECT value_id FROM catalog_product_entity_datetime GROUP BY entity_id, attribute_id, store_id HAVING COUNT(*) > 1) AS temp);
DELETE FROM catalog_product_entity_decimal WHERE value_id IN (SELECT value_id FROM (SELECT value_id FROM catalog_product_entity_decimal GROUP BY entity_id, attribute_id, store_id HAVING COUNT(*) > 1) AS temp);

Die eigentliche Frage ist, wie man überhaupt zu so einer EAV-Struktur kommen konnte. Das kann eigentlich nicht passieren, denn es gibt einen Unique-Index über die Felder (attribute_id, entity_id, store_id). Per SQL kann man diese aber über mit “SET  UNIQUE_CHECKS=0″ umgehen, was zum Beispiel am Anfang eines phpMyAdminDumps immer gemacht wird. Der “Trick” wird auch von eingen Extensions benutzt, um schneller in die Datenbank zu schreiben.


Unterschiedliche Toolbars in der Produktliste

Veröffentlicht am 22.08.2010 von jkuensebeck in der Schublade Magento-Templates | Tags: , | 2 Kommentare »

Das Problem

2 verschiedene Toolbars in Magento
Ich habe gerade dieses Design auf dem Tisch. Eine Produktliste, oben eine Toolbar mit Sortieroptionen, unten eine Toolbar mit Pager, bestimmt kein Problem: Die Template-Engine von Magento ist doch wie gemacht für so etwas.
zum kompletten Eintrag »


Model->load($id) vs. Model->getCollection()->getItemById($id)

Veröffentlicht am 20.08.2010 von jkuensebeck in der Schublade Magento | Tags: , , | Ein Kommentar »

Neulich bin ich in einer älteren Version einer in Deutschland sehr beliebten Extension über einen lustigen kleinen Performance-Killer gestolpert: Es sollte ein Quote-Object anhand der ID geladen werden, das sah im Code folgendermaßen aus:

$quote = Mage::getModel('sales/quote')->getCollection()->getItemById($quote_id);

harmlos, oder? Nein!

Diese eine Zeile brauchte ca. 30 Sekunden, und das auf einem wirklich performanten Kundenserver.
Wie kommt’s?
zum kompletten Eintrag »


Unübersetzte Strings finden

Veröffentlicht am 17.08.2010 von jkuensebeck in der Schublade Magento | Tags: , | Ein Kommentar »

Als dirty Hack einfach die Mage::log(…) Zeile zwischen DEN BEIDEN SCHREIENDEN KOMMENTAREN!!! in app/code/core/Mage/Core/Model/Translate.php einfügen:

/**
 * Return translated string from text.
 *
 * @param string $text
 * @param string $code
 * @return string
 */
 protected function _getTranslatedString($text, $code)
 {
   $translated = '';
   if (array_key_exists($code, $this->getData())) {
     $translated = $this->_data[$code];
   }
   elseif (array_key_exists($text, $this->getData())) {
     $translated = $this->_data[$text];
   }
   else {
     $translated = $text;
     // THE LINE THAT SAVES THE DAY FOLLOWS:
     Mage::log('UNTRANSLATED STRING: "'.$code.' - '.$text.'"');
     // THAT WAS THE LINE THAT SAVED THE DAY
   }
   return $translated;
}

und anschliessend sich die fehlenden Übersetzungen per

grep 'UNTRANSLATED STRING' var/log/system.log

anzeigen lassen.

Vielleicht gibt es das später auch noch mal in schön, mal sehen…


HOW-TO: Der Autovervollständigung auf die Sprünge helfen und die eigene Produktivität um ca. 170% steigern

Veröffentlicht am 17.08.2010 von jkuensebeck in der Schublade Magento, Magento-Templates | Tags: , , , | 2 Kommentare »

Da ich der Meinung bin, dass das Lesen von Dokumentationen Verschwendung meiner wertvollen Zeit ist, lasse ich das lieber von anderen erledigen, z.B. meiner IDE (d.h. momentan Netbeans, mit PDT für Eclipse funktioniert der ganze Spass aber genauso).

Die Autovervollständigung der IDE

Meistens funktioniert die Autovervollständigung bei der Magento-Entwicklung ja recht gut, wenn ich z.B. in einem eigenen Controller zum kompletten Eintrag »


Magento SQL Profiler

Veröffentlicht am 07.08.2010 von jkuensebeck in der Schublade Magento | Tags: , , , | Ein Kommentar »

Magento (bzw. wir das Zend-Framework) hat einen eingebauten SQL-Profiler im Gepäck, um diesen zu aktivieren einfach in der local.xml im Connection-Knoten folgende Zeile ergänzen:

<resources>
 <db>
 <table_prefix><![CDATA[]]></table_prefix>
 </db>
 <default_setup>
 <connection>
 <host><![CDATA[localhost]]></host>
 <username><![CDATA[root]]></username>
 <password><![CDATA[]]></password>
 <dbname><![CDATA[magento_test]]></dbname>
 <active>1</active>
 <profiler>1</profiler>
 </connection>
 </default_setup>
 </resources>

zum kompletten Eintrag »