Posting in the Magento forums has been disabled pending the implementation of a new and improved forum solution which should better serve the community.

For new questions please post at magento.stackexchange.com, the community-run support site for the Magento community. We will be providing updates on the new forum solution soon. For questions or concerns please email community@magento.com.

Magento Forum

Via SOAP Kategorien mit vordefinierten IDs anlegen? 
 
Trockenbrot
Jr. Member
 
Avatar
Total Posts:  6
Joined:  2009-03-02
 

Hallöchen,
ich versuche mich seit kurzem daran mich in den Magento Code einzuleben. *hust* Garnicht so leicht.  ohh

Im Moment stehe ich vor dem Problem, das ich unseren internen Kategorienbaum gern in den Magentoshop importieren und auch laufend aktualisieren möchte. Hierzu greife ich auf die API via SOAP zu. (So geschieht das meinem derzeitigen shop ebenfalls).

Die Kategorientabellen sind in der Grundstruktur kompatibel. Die 5 wichtigsten Felder kann ich abfragen:
[category_ID] [parent_ID] [name] [is_active] [updated_at]

Nach dem ersten Upload von 10 Kategorien war ich total happy das es so wunderbar klappt!
Beim zweiten upload war die Freude dann dahin, denn dann mußte ich feststellen das Magento seine Category_id selbstständig hochzählt. Damit deckt sie sich nicht mehr mit den Daten die ich übermitteln möchte und ein heilloser Kategorienknoten entsteht.
Um das zu lösen habe ich versucht mit einem update nach einem create die ID neu zu setzen. Leider erfolglos.
Hier mal mein Code: (Vielleicht habe ich ja ein denkfehler drin)

#SQL-Abfrage
$sql_query tep_db_query("SELECT c.`categories_id` AS category_id, cd.`categories_name` AS name, c.`parent_id` AS parent_id, c.`categories_status` AS is_active, FROM_UNIXTIME(c.updated) AS updated_at FROM `categories` AS c LEFT JOIN `categories_description` AS cd ON c.categories_id = cd.categories_id WHERE c.`categories_status` = 1 AND c.categories_id < 10");
while (
$category_data tep_db_fetch_array($sql_query)) {
    $error 
mage_sync_categories($category_data$language_id);
    
}
function mage_sync_categories($data$language_id '2'$location 'http://www.devo-maschinen.de/api/soap/index/wsdl/1/'{
  $new_category 
false;

  
#SOAP-Connect
  
$client = new SoapClient('http://www.devo-maschinen.de/api/soap/index/wsdl/1/');
  
$soap_session $client->login(DEMA_USERDEMA_PASSWORD);
  
  
// Get Catergory Data via ID
  
try {
    $cat_data 
$client->call($soap_session'category.info'$data['category_id']);
    
}
  
catch (Exception $e{
    update_process_log
(get_class($e)." within the exception handler. Message: ".$e->getMessage()." on line ".$e->getLine()."<br />\r\n"$write_log true);
    if(
is_soap_fault($e)) {
      
if ($e->faultcode == '102'// 102 => Category not exists
        
$new_category true;
        
}
      
else {
        Soap_Exeption_Log
($e$client);
        
}
      }
    }
  
if ($new_category{
    
// Create new Category
    
try {
      $cat_id 
$client->call($soap_session
                                
'category.create'
                                array(
$data['parent_id'],
                                      
$data));
      
}
    
catch (Exception $e{
      update_process_log
(get_class($e)." within the exception handler. Message: ".$e->getMessage()." on line ".$e->getLine()."<br />\r\n"$write_log true);
      if(
is_soap_fault($e)) {
        Soap_Exeption_Log
($e$client);
        
}
      }
    
// Update newly created category_id
    
try {
      $cat_data 
$client->call($soap_session
                                
'category.update'
                                array(
$cat_id,
                                      array(
'category_id' => $data['category_id'])));
      
}
    
catch (Exception $e{
      update_process_log
(get_class($e)." within the exception handler. Message: ".$e->getMessage()." on line ".$e->getLine()."<br />\r\n"$write_log true);
      if(
is_soap_fault($e)) {
        Soap_Exeption_Log
($e$client);
        
}
      }
    }
  
else {
    
// nothing yet
    
}
  print_r
($cat_data);
  echo 
"<hr />";
  
}

Leider fruchtet der Code nicht, es wird immer und immer wieder eine neue Kategorie mit neuer ID angelegt. Und deren ID läßt sich leider nicht aktualisieren.  grrr

Beim versuch die APIs mal näher anzuschauen um herauszufinden woran es denn scheitert, bin ich letztendlich in der app\code\core\Mage\Catalog\Model\Category\Api.php gelandet. Hier steck ich nun an den Funktionen SetData(), GetData() und Save() fest. Wo sind die denn definiert?

Danke schonmal im vorraus.

 
Magento Community Magento Community
Magento Community
Magento Community
 
Dscho
Sr. Member
 
Avatar
Total Posts:  236
Joined:  2007-10-05
Singen, Germany
 

Hallo,

mich hat das nun auch interessiert und ich habe einfach statisch versucht eine Artikelgruppe zu verändern.

$cat $proxy->call($sessionId'catalog_category.info'20); 
  
$newData = array('category_id'=>2000);
  
// update created category on German store view
  
$proxy->call($sessionId'category.update', array(20$newData));

Also das geht definitiv nicht - hätte mich auch schwer gewundert. In fast allen Shops sind ID’s autoincrement Felder.
Aus Sicherheitsgründen und zur Vermeidung von Fehlern wird das Ändern der category_id vermutlich verhindert.
Ich habe auch schon versucht tiefer in das Thema API einzusteigen und bin leider auch nicht weiter gekommen.

In der Datei app\code\core\image\catalog\model\category\API.php befindet sich die Funktion update.

public function update($categoryId$categoryData$store null)
    
{
        $category 
$this->_initCategory($categoryId$store);

        foreach (
$category->getAttributes() as $attribute{
            
if ($this->_isAllowedAttribute($attribute)
                && isset(
$categoryData[$attribute->getAttributeCode()])) {
                $category
->setData(
                    
$attribute->getAttributeCode(),
                    
$categoryData[$attribute->getAttributeCode()]
                
);
            
}
        }

        
try {
            $category
->save();
        
catch (Mage_Core_Exception $e{
            $this
->_fault('data_invalid'$e->getMessage());
        
}

        
return true;
    
}

Ich denke man muss sich die Funktion save() genauer ansehen. Diese verhindert wohl das ändern der ID.
Ich hoffe auch auf baldiges Feedback.

Viele Grüße
Dscho

 
Magento Community Magento Community
Magento Community
Magento Community
 
Trockenbrot
Jr. Member
 
Avatar
Total Posts:  6
Joined:  2009-03-02
 

Hi,

ich habe eine save funktion gefunden. (app\code\core\Mage\Catalog\Model\Convert\Adapter\catalog.php)
Aber scheinbar ist das wohl die falsche, denn:

public function save()
    
{
        
/*
        $res = $this->getResource();
        foreach (array('Attributes', 'Attribute Sets', 'Attribute Options', 'Products', 'Categories', ''))
        $this->setData
        echo "<pre>".print_r($this->getData(),1)."</pre>";
        */
        
return $this;
    
}

eine komplett auskommentierte funktion die nur ein $this (Woher kommt das ?!?) zurück gibt, erscheint mir doch recht überflüssig.
Ok, mit Objekten hab ichs bisweilen nicht so gehabt. Bitte erleuchtet mich, wenn das so tatsächlich Sinn macht.  cool smile
---------------------

Ein anderer Lösungsansatz für den Import der eigenen Cat_IDs wäre eine zusätzliche Tabelle, welche die Magento-IDs mit den eigenen “verlinked”. Damit könnte das Autoincrement des Shops uneingeschränkt weiter laufen und man hätte trotzdem seine eigenen Cat-IDs.
Wäre das mit den Shop-Updates denn verträglich?

 
Magento Community Magento Community
Magento Community
Magento Community
 
Dscho
Sr. Member
 
Avatar
Total Posts:  236
Joined:  2007-10-05
Singen, Germany
 

Ich habe mich auch schon geärgert dass man Artieklgruppen nicht einfach importieren kann.
Ich dachte da eher daran, dass man einen Pfad angeben kann.

Beispiel für Import:
SKU;Name;Artikelgruppe
100;Produkt1;Produkte/Artikelgruppe1
200;Produkt2;Produkte/Artikelgruppe2
300;Produkt3;Produkte/Artikelgruppe2/Unterartigelgruppe

usw.

Aber ich hatte noch keine Zeit mich damit genauer zu beschäftigen. Aber ich denke dass man das eher hinbekommt als die Synchronisation von ID’s.

Viele Grüße
Dscho

 
Magento Community Magento Community
Magento Community
Magento Community
 
Trockenbrot
Jr. Member
 
Avatar
Total Posts:  6
Joined:  2009-03-02
 

In meinem Fall habe ich das Problem, das die Kategorienliste in einem anderen System gepflegt wird. Hierdurch kommt es immer wieder zu verschieben, löschen oder einfach nur umbenennen von Kategorien. Diese änderungen dann an Magento weiter zu geben wird noch ein hartes Stück arbeit. Via einer “Link-Tabelle” war jetzt auch nur so der erste Gedanke. Vielleicht, *hust* hoffentlich LOL gibt es da eine viel einfachere Lösung.

Deine Idee die Kategorien beim Produkte pflegen mit anzulegen, finde ich sehr gut!
Dazu müßte man den Kategorienbaum statt auf die ID, auf die Namen aufbauen. Theoretisch möglich, praktisch könnte man z.b. an Sonderzeichen im Namen scheitern.
Ist die Spalte “Name” eigentlich indiziert? Wenn nicht, muss das nachgeholt werden, da sonst die Performance gewaltig leidet.
Nach einem upload müßte man auch gleich auf “gelöschte” bzw. umbenannte Kategorien prüfen und diese löschen.

Hm, aber irgendwas stört mich noch an der verwendung der Namen als Index. Nur komm ich grad nicht drauf was es ist.  rolleyes

EDIT:
Habe eine weitere save() Funktion gefunden, die vermutlich eher diejenige ist, die von den create/updates aufgerufen wird.
app\code\core\Mage\Core\Model\Mysql4\abstract.php

public function save(Mage_Core_Model_Abstract $object)
    
{
        
if ($object->isDeleted()) {
            
return $this->delete($object);
        
}

        $this
->_beforeSave($object);
        
$this->_checkUnique($object);

        if (!
is_null($object->getId())) {
            $condition 
$this->_getWriteAdapter()->quoteInto($this->getIdFieldName().'=?'$object->getId());
            
$this->_getWriteAdapter()->update($this->getMainTable(), $this->_prepareDataForSave($object), $condition);
        
else {
            $this
->_getWriteAdapter()->insert($this->getMainTable(), $this->_prepareDataForSave($object));
            
$object->setId($this->_getWriteAdapter()->lastInsertId($this->getMainTable()));
        
}

        $this
->_afterSave($object);

        return 
$this;
    
}
Bei dem Anblick hab ich erstmal abgeschalten und mich entschlossen mich in die Objektorientierte programmierung etwas besser einzulesen.  red face
 
Magento Community Magento Community
Magento Community
Magento Community
 
Trockenbrot
Jr. Member
 
Avatar
Total Posts:  6
Joined:  2009-03-02
 

Nach eingehendem studieren einer Handvoll OOP PHP Seiten bin ich jetzt -hoffentlich- etwas schlauer. (Die coolste/lustigste Erklärung gibts übrigens auf: www.peterkropff.de.)

Die create()/ update() Methoden in der \app\code\core\Mage\Catalog\Model\Category\api.php prüfen die erlaubten “Felder” mit der Methode _isAllowedAttribute welche sich in der \app\code\core\Mage\Catalog\Model\Api\Ressouce.php befindet und eine Kindklasse von Mage_Api_Model_Resource_Abstract ist (Darin ist die create() Methode).

Hier mal der Code:

protected function _isAllowedAttribute($attribute$attributes null)
    
{
        
if (is_array($attributes)
            && !( 
in_array($attribute->getAttributeCode(), $attributes)
                  || 
in_array($attribute->getAttributeId(), $attributes))) {
            
return false;
        
}

        
return !in_array($attribute->getFrontendInput(), $this->_ignoredAttributeTypes)
               && !
in_array($attribute->getAttributeCode(), $this->_ignoredAttributeCodes);
    
}

Wenn ich mir das so anschaue, müßte man doch eigentlich “nur” die Zeile:

|| in_array($attribute->getAttributeId(), $attributes)
herausnehmen um die ID ebenfalls zur aktualisierung “freizugeben”.

Oder habe ich was übersehen, das dagegen spricht? Jetzt mal die Tatsache weggedacht, das man die original Skripte nicht bearbeiten sollte.  smile

EDIT:
Ok bin auf dem Holzweg! Ich hab Spaßeshalber die funktions mal gänzlich rausgenommen. Das ergebnis war weiterhin das selbe.
Es war nicht möglich auch nur irgend ein ID Feld per update zu aktualisieren. Name hingegen ging problemlos.
Also weiter suchen.

EDIT 2:
Ich hab mich darauf versteift die IDs meinen wünschen entsprechend anzupassen. Das muss irgendwie machbar sein! smile
Via Update wird es aber definitiv nicht gehen. Aber beim create selbst, besteht evtl. die Möglichkeit.
Bis zum ausführen der save() funktion existiert im Objekt “category” noch keine entity_id. Also wird diese irgendwo in der save() ermittelt.

 
Magento Community Magento Community
Magento Community
Magento Community
 
Trockenbrot
Jr. Member
 
Avatar
Total Posts:  6
Joined:  2009-03-02
 

Kurz vor dem WE noch ein Status-Update smile

Ich glaube ich habe nun einen Weg gefunden. Zugegeben, noch ist er nicht ausgereift, aber immerhin haben die ersten uploads funktioniert!

Zuerst habe ich die Standard create funktion kopiert und eine leicht modifizierte angelegt. (XML Anpassungen notwendig, damit die Funktion angesprochen werden kann!)
Hier der noch nicht modifizierte code:

public function createwithid($parentId$categoryData$store null)
 
{...
                        if (
$this->_isAllowedAttribute($attribute)
                && isset(
$categoryData[$attribute->getAttributeCode()])) {
...
}
Diesen Teil habe ich entfernt::
$this->_isAllowedAttribute($attribute)
                &&
Damit habe ich die Index-Feldprüfung ausgehebelt. (unschön ich weiß wink )
Bei dem createaufruf:
$soap_data $client->call($soap_session
                                
'category.createwithid'
                                array(
$data['parent_id'],
                                
$data));
müssen in $data nun zusätzlich folgende Felder gepflegt sein:
entity_id, parent_id, path
ausserdem wäre es gut wenn die felder
position, level
ebenfalls gepflegt sind. Sonst werden sie standardmäßig mit “0” angelegt. Ob das später zu Problemen führt, weiß ich im moment noch nicht. Vermutlich aber schon.

Mit dem Feld path habe ich Anfangs meine schwierigkeiten gehabt, da ich erstmal unseren Kategorien-ID Baum glech dem des Magento systems erstellen musste. Plus die Root-Shop-Kategorie, welche die ersten 2 Werte im path ist.
Bei einem Standard-Webauftritt mit nur einem Shop ist das normalerweise “1/2”. In meinem Fall könnten mehrere Shops entstehen, also versuchte ich das gleich so zu machen, das es multi-Shop-fähig ist. Aber ich scheiterte am abfragen der Rootkategorien. Naja… irgendwann hab ich es auf eis gelegt und erstmal mit dem standard versucht.  LOL

Das scheint nun soweit zu funktionieren. Ich werde aber erst nächste Woche genauere tests durchführen können.

 
Magento Community Magento Community
Magento Community
Magento Community
 
Trockenbrot
Jr. Member
 
Avatar
Total Posts:  6
Joined:  2009-03-02
 

Nach ein paar Tagen des ausprobierens und einem anschließenden upload/update eines Kategoriebaums von rund 700 Einträgen, trau ich mich zu sagen: Es funktioniert!  LOL

Mein Folgeproblem ist nun nur noch:
Ich habe einen riesigen Kategorienbaum im Shop, aber solang sich keine Produkte in einer Kategorie oder deren Kindkategorie befinden, sollte diese auch nicht angezeigt werden.

Wär schön wenn es im System eine Logik gäbe die das von allein aushandelt.
Ansonsten muss ich eben beim upload entsprechend vorab filtern.

 
Magento Community Magento Community
Magento Community
Magento Community
Magento Community
Magento Community
Back to top