2012-01-22 9 views
11

Buona giornata!Come posso creare un prodotto con attributi aggiuntivi in ​​Magento via Soap/Java

Vorrei utilizzare API SOAP del Magento per gestire il catalogo dei prodotti, attributi ecc sto correndo seguente configurazione: - il rispetto

  • Magento 1.6
  • API SOAP WS-I
  • Mac OSX Lion
  • Mamp 2.0.5

Nel caso in cui qualcuno vuole creare un nuovo prodotto, è necessario impostare una fe w proprietà dell'oggetto del prodotto. codice seguente dimostrare il mio approccio per fare questo:

public int createProduct(DatabaseProduct product) { 

     ArrayOfString categories = new ArrayOfString(); 
       categories.getComplexObjectArray().add(categoryID); 
     createEntity.setCategoryIds(categories); 

     CatalogProductCreateEntity createEntity = populateCreateOrUpdateEntity(product); 

     CatalogProductCreateRequestParam param = new CatalogProductCreateRequestParam(); 
     param.setSessionId(sessionId); 
     param.setSet(setId); 
     param.setSku(product.getSku()); 
     param.setType("simple"); 
     param.setStore(storeId); 
     param.setProductData(createEntity); 

     CatalogProductCreateResponseParam response = service.catalogProductCreate(param); 
     return response.getResult(); 
    } 

    private CatalogProductCreateEntity populateCreateOrUpdateEntity(DatabaseProduct product) { 

     CatalogProductCreateEntity createEntity = new CatalogProductCreateEntity(); 
     createEntity.setShortDescription(product.getDescription().substring(0, 20) + "..."); 
     createEntity.setDescription(product.getDescription()); 
     createEntity.setName(product.getName()); 
     createEntity.setPrice(String.valueOf(product.getPrice())); 
     createEntity.setStatus("1"); //active 
     createEntity.setVisibility("4"); //visible in search/catalog 
     createEntity.setWeight("70"); //some value 
     createEntity.setTaxClassId("2"); //standard 

      AssociativeArray attributes = new AssociativeArray();    

      AssociativeEntity attr1 = new AssociativeEntity(); 
      attr1.("attribute1_key"; 
      attr1.("attribute1_value"); 
      attributes.getComplexObjectArray().add(attr1); 

      AssociativeEntity attr2 = new AssociativeEntity(); 
      attr2.("attribute2_key"); 
      attr2.("attribute2_value"); 
      attributes.getComplexObjectArray().add(attr2); 

     createEntity.setAdditionalAttributes(attributes); 

     return createEntity; 
    } 

mi sono reso conto che ho un errore scritto nel "system.log" di Magento.

2012-01-21T09:41:01+00:00 DEBUG (7): First parameter must either be an object or the name of an existing class/opt/website/magento/app/code/core/Mage/Catalog/Model/Product/Api/V2.php 

ho potuto localizzare l'errore nel file "V2.php" on line 265. Secondo la documentazione php.net il metodo "property_exists()" solo è possibile verificare la presenza di campi in oggetti. In effetti la variabile "$productData" contiene una proprietà denominata "additional_attributes" che è della matrice di tipi. Pertanto l'esecuzione di questo codice causerà un errore.

Inoltre non so riprodurre l'oggetto la struttura dell'oggetto "$productData" tramite l'utilizzo dell'API SOAP di Magento.

Se esamino questo codice ("foreach 'loop) in linea 270, significa che v'è un oggetto (' $productData ') che tiene una matrice (' additional_attributes") che a sua volta deve incapsulare un insieme di coppie chiave/valore (se ho ragione)

253  protected function _prepareDataForSave ($product, $productData) 
254  { 
255   if (property_exists($productData, 'website_ids') && is_array($productData->website_ids)) { 
256    $product->setWebsiteIds($productData->website_ids); 
257   } 
258 
259   Mage::log("debug1"); 
260   Mage::log(property_exists($productData, 'additional_attributes')); 
261   
262   Mage::log($productData); 
263   
264   if (property_exists($productData, 'additional_attributes')) { 
265    if (property_exists($productData->additional_attributes, 'single_data')) { 
266     
267     Mage::log("---> single"); 
268     Mage::log($productData->additional_attributes); 
269     
270     foreach ($productData->additional_attributes->single_data as $_attribute) { 
271      $_attrCode = $_attribute->key; 
272      $productData->$_attrCode = $_attribute->value; 
273     } 
274    } 
275    if (property_exists($productData->additional_attributes, 'multi_data')) { 
276     
277     Mage::log("---> multi"); 
278     Mage::log($productData->additional_attributes); 
279     
280     foreach ($productData->additional_attributes->multi_data as $_attribute) { 
281      $_attrCode = $_attribute->key; 
282      $productData->$_attrCode = $_attribute->value; 
283     } 
284    } 
285     
286    Mage::log("debugXXX"); 
287    unset($productData->additional_attributes); 
288   } 
289   
290   Mage::log("debug2"); 
291   
292   foreach ($product->getTypeInstance(true)->getEditableAttributes($product) as $attribute) { 
293    $_attrCode = $attribute->getAttributeCode(); 
294    if ($this->_isAllowedAttribute($attribute) && (isset($productData->$_attrCode))) { 
295     $product->setData(
296   ... etc ... 

Questo sembra essere un bug. Quindi questa è la mia domanda.

Sto andando bene a chiamare questo un problema di programmazione che deve essere inserito nella base del bug? C'è un modo per superare questo problema? Devo riscrivere parti del codice php da sopra per soddisfare la mia necessità di gestire le informazioni sul prodotto per creare correttamente un prodotto?

Grazie in anticipo

$productData 
    (
      [name] => testname 
      [description] => testdescription 
      [short_description] => shorttestdescription 
      [weight] => 70 
      [status] => 1 
      [visibility] => 4 
      [price] => 359.0 
      [tax_class_id] => 2 
      [additional_attributes] => Array 
      (
        [attribute1] => 999.0 
        [attribute2] => testcontent 
      ) 
    ) 

il CatalogProductCreate-Call dal WSDL generato da SoapUI:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:Magento"> 
    <soapenv:Header/> 
    <soapenv:Body> 
     <urn:catalogProductCreateRequestParam> 
     <sessionId>?</sessionId> 
     <type>?</type> 
     <set>?</set> 
     <sku>?</sku> 
     <productData> 
      <!--Optional:--> 
      <categories> 
       <!--Zero or more repetitions:--> 
       <complexObjectArray>?</complexObjectArray> 
      </categories> 
      <!--Optional:--> 
      <websites> 
       <!--Zero or more repetitions:--> 
       <complexObjectArray>?</complexObjectArray> 
      </websites> 
      <!--Optional:--> 
      <name>?</name> 
      <!--Optional:--> 
      <description>?</description> 
      <!--Optional:--> 
      <short_description>?</short_description> 
      <!--Optional:--> 
      <weight>?</weight> 
      <!--Optional:--> 
      <status>?</status> 
      <!--Optional:--> 
      <url_key>?</url_key> 
      <!--Optional:--> 
      <url_path>?</url_path> 
      <!--Optional:--> 
      <visibility>?</visibility> 
      <!--Optional:--> 
      <category_ids> 
       <!--Zero or more repetitions:--> 
       <complexObjectArray>?</complexObjectArray> 
      </category_ids> 
      <!--Optional:--> 
      <website_ids> 
       <!--Zero or more repetitions:--> 
       <complexObjectArray>?</complexObjectArray> 
      </website_ids> 
      <!--Optional:--> 
      <has_options>?</has_options> 
      <!--Optional:--> 
      <gift_message_available>?</gift_message_available> 
      <!--Optional:--> 
      <price>?</price> 
      <!--Optional:--> 
      <special_price>?</special_price> 
      <!--Optional:--> 
      <special_from_date>?</special_from_date> 
      <!--Optional:--> 
      <special_to_date>?</special_to_date> 
      <!--Optional:--> 
      <tax_class_id>?</tax_class_id> 
      <!--Optional:--> 
      <tier_price> 
       <!--Zero or more repetitions:--> 
       <complexObjectArray> 
        <!--Optional:--> 
        <customer_group_id>?</customer_group_id> 
        <!--Optional:--> 
        <website>?</website> 
        <!--Optional:--> 
        <qty>?</qty> 
        <!--Optional:--> 
        <price>?</price> 
       </complexObjectArray> 
      </tier_price> 
      <!--Optional:--> 
      <meta_title>?</meta_title> 
      <!--Optional:--> 
      <meta_keyword>?</meta_keyword> 
      <!--Optional:--> 
      <meta_description>?</meta_description> 
      <!--Optional:--> 
      <custom_design>?</custom_design> 
      <!--Optional:--> 
      <custom_layout_update>?</custom_layout_update> 
      <!--Optional:--> 
      <options_container>?</options_container> 
      <!--Optional:--> 
      <additional_attributes> 
       <!--Zero or more repetitions:--> 
       <complexObjectArray> 
        <key>?</key> 
        <value>?</value> 
       </complexObjectArray> 
      </additional_attributes> 
      <!--Optional:--> 
      <stock_data> 
       <!--Optional:--> 
       <qty>?</qty> 
       <!--Optional:--> 
       <is_in_stock>?</is_in_stock> 
       <!--Optional:--> 
       <manage_stock>?</manage_stock> 
       <!--Optional:--> 
       <use_config_manage_stock>?</use_config_manage_stock> 
       <!--Optional:--> 
       <min_qty>?</min_qty> 
       <!--Optional:--> 
       <use_config_min_qty>?</use_config_min_qty> 
       <!--Optional:--> 
       <min_sale_qty>?</min_sale_qty> 
       <!--Optional:--> 
       <use_config_min_sale_qty>?</use_config_min_sale_qty> 
       <!--Optional:--> 
       <max_sale_qty>?</max_sale_qty> 
       <!--Optional:--> 
       <use_config_max_sale_qty>?</use_config_max_sale_qty> 
       <!--Optional:--> 
       <is_qty_decimal>?</is_qty_decimal> 
       <!--Optional:--> 
       <backorders>?</backorders> 
       <!--Optional:--> 
       <use_config_backorders>?</use_config_backorders> 
       <!--Optional:--> 
       <notify_stock_qty>?</notify_stock_qty> 
       <!--Optional:--> 
       <use_config_notify_stock_qty>?</use_config_notify_stock_qty> 
      </stock_data> 
     </productData> 
     <!--Optional:--> 
     <store>?</store> 
     </urn:catalogProductCreateRequestParam> 
    </soapenv:Body> 
</soapenv:Envelope> 
+0

cosa viene prodotto di "product_data'? incolla qui. –

risposta

8

Per la V2 API SOAP sembra che abbiamo bisogno di nido le additional_attributes in un multi_data o strato di single_data?

Guardando app/code/core/Mage/Catalogo/modello/prodotto/Api/V2.php # 256 Penso che abbiamo bisogno di usare

$manufacturer = new stdClass(); 
$manufacturer->key = "manufacturer"; 
$manufacturer->value = "20"; 
$additionalAttrs['single_data'][] = $manufacturer; 

o

$manufacturer = new stdClass(); 
$manufacturer->key = "manufacturer"; 
$manufacturer->value = "20"; 
$additionalAttrs['multi_data'][] = $manufacturer; 

di essere utilizzato come:

$productData = new stdClass(); 
    $additionalAttrs = array(); 

      // manufacturer from one of the two above^

    $productData->name     = $data['name']; 
    $productData->description   = $data['description']; 
    $productData->short_description  = $data['short_description']; 
    $productData->weight     = 0; 
    $productData->status     = 2; // 1 = active 
    $productData->visibility    = 4; //visible in search/catalog 
    $productData->category_ids   = $data['categories']; 
    $productData->price     = $data['price']; 
    $productData->tax_class_id   = 2; // 2=standard 
    $productData->additional_attributes = $additionalAttrs; 

    // Create new product 
    try { 
     $proxy->catalogProductCreate($sessionId, 'virtual', 9, $sku, $productData); // 9 is courses 
    } catch (SoapFault $e) { 
     print $e->getMessage(); //Internal Error. Please see log for details. 
     exit(); 
    } 
+0

questo è corretto! ma non è possibile la soap api generata dalla wsdl. – stereoscope

+0

Non capisco cosa intendi per non è possibile? – creuzerm

+2

le classi generate da wsdl non forniscono la struttura dati per creare un set singolo o multidata. pertanto non è possibile raggruppare i dati in una richiesta. – stereoscope

3

Questo non è un bug. Ho usato questa API V2 di Magento SOAP per più di un anno, e il concetto che il team di Magento ha applicato qui è assolutamente corretto.

Prima di tutto, ogni volta che qualcuno che utilizza l'API SOAP V2 deve controllare completamente il WSDL del rispettivo Magento, in modo che possa creare/chiamare correttamente i messaggi. L'URL per caricare il WSDL dell'API SOAP V2 è "<your_magento_home_page_url>/api/v2_soap/index/wsdl/1".

Ora tornando alla tua domanda, il tipo di elemento "additional_attributes" è "associativeArray", il che significa che la sua XML dovrebbe assomigliare a: -

<additional_attributes> 
    <!-- 
    This XML tag "item" can be anything; 
    it's what I use, but can definitely be any other valid non-used literal. 
    --> 
    <item> 
    <key>attribute_1_code</key> 
    <value>attribute_1_value_as_defined_in_database</value> 
    </item> 
    <item> 
    <key>attribute_2_code</key> 
    <value>attribute_2_value_as_defined_in_database</value> 
    </item> 
</additional_attributes> 

Un esempio del formato XML di cui sopra sarà : -

<additional_attributes> 
    <item> 
    <key>color</key> 
    <!-- 
    I haven't provided the name/string "Blue", 
    because Magento's EAV database structure will only hold the option value 
    (which is a unique ID) and not the option literal string. 
    --> 
    <value>56</value> <!-- assuming this value for "Blue" color --> 
    </item> 
    <item> 
    <key>manufacturer</key> 
    <value>87</value> <!-- assuming this value for the manufacturer "Intel" --> 
    </item> 
</additional_attributes> 

Quindi, la variabile "$productData" deve contenere i valori in questo modo: -

$productData 
(
    [name] => testname 
    [description] => testdescription 
    [short_description] => shorttestdescription 
    [weight] => 70 
    [status] => 1 
    [visibility] => 4 
    [price] => 359.0 
    [tax_class_id] => 2 
    [additional_attributes] => Array 
    (
     [0] => Array 
     (
      [key] => attribute1 
      [value] => 999.0 
     ) 
     [1] => Array 
     (
      [key] => attribute2 
      [value] => testcontent 
     ) 
    ) 
) 

Spero che aiuti.

+0

Ciao! Grazie. Sono a conoscenza dell'URL da usare: .../api/v2_soap/index/wsdl/1 o .../api/v2_soap? Wsdl = 1. Quindi, se creo un array associativo, posso semplicemente riempirlo con valori stringa. Inoltre, ho creato i file Java da wsdl con Apache CXF – stereoscope

+0

@fritz: ottimo per sentirlo. Spero che ora sarai in grado di risolverlo. :) –

+0

Mi dispiace dover rivedere il mio codice, ma se creo un associativearray posso aggiungere solo associatenze ma non associativearray. quindi non è possibile costruire questo tipo di infrastruttura che hai descritto. Finalmente farò una revisione del codice e pubblicherò i miei progressi domani. – stereoscope

7

In realtà ho dovuto applicare patch app/code/core/Mage/Catalog/Model/Product/Api/V2.php per far funzionare questa chiamata nella versione 1.6.2.0.

Il codice controlla esistenti sia per una "single_data" o "multi_data" attributo sotto proprietà 'additional_attributes' e cerca di iterare l'quelli come un array associativo:

if (property_exists($productData, 'additional_attributes')) { 
     if (property_exists($productData->additional_attributes, 'single_data')) { 
      foreach ($productData->additional_attributes->single_data as $_attribute) { 
       $_attrCode = $_attribute->key; 
       $productData->$_attrCode = $_attribute->value; 
      } 
     } 
     if (property_exists($productData->additional_attributes, 'multi_data')) { 
      foreach ($productData->additional_attributes->multi_data as $_attribute) { 
       $_attrCode = $_attribute->key; 
       $productData->$_attrCode = $_attribute->value; 
      } 
     } 
} 

Penso che la questione è che dal momento che stiamo passando la struttura array associativo:

<item> 
    <key>...</key> 
    <value>...</value> 
</item> 
<item> 
    <key>...</key> 
    <value>...</value> 
</item> 

direttamente sotto le additional_attribtutes blocco allora è veramente la proprietà additional_attributes che deve essere iterata nel corso di tirare la chiave di attributo/valori, così ho aggiunto terzo se blocco:

if (gettype($productData->additional_attributes) == 'array') { 
      foreach ($productData->additional_attributes as $k => $v) { 
        $_attrCode = $k; 
        $productData->$_attrCode = $v; 
      } 
    } 

Con quel codice in atto i miei attributi personalizzati vengono aggiunti/aggiornati.

Ecco un esempio di richiesta:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:Magento"> 
<soapenv:Header/> 
<soapenv:Body> 
    <urn:catalogProductUpdateRequestParam> 
    <sessionId>100fe1f9d0518b0fd0ed49cc460c1fa6</sessionId> 
    <productId>1</productId> 
    <productData> 
     <name>product 3</name> 
     <!-- the custom attributes to updated.... 
     --> 
     <additional_attributes> 
      <complexObjectArray> 
       <key>feed_id</key> 
       <value>56920</value> 
      </complexObjectArray> 
      <complexObjectArray> 
       <key>feed_active</key> 
       <value>1</value> 
      </complexObjectArray> 
     </additional_attributes> 
     </productData> 
    </urn:catalogProductUpdateRequestParam> 
    </soapenv:Body> 
</soapenv:Envelope> 
+0

Sei un genio, grazie. Tutte le altre risposte non funzionano con un proxy generato da Visual Studio. –

+0

Ottimo! Questa era anche la soluzione al mio problema: http://magento.stackexchange.com/questions/1308/why-does-one-of-many-attributes-does-not-get-updated-with-soapv2-ws- i –

+1

Questa è la risposta da utilizzare se si genera codice dal WSDL e si può anche modificare il codice PHP Magento. Posso confermare che il problema esiste in 1.9.1 e questa correzione mi ha permesso di aggiornare gli attributi. –

2

stroisi è quasi completamente corretto. Solo una correzione per questa risposta: la terza condizione che hai aggiunto valuterà a true anche per le prime due condizioni (aggiungendo quindi tali attributi due volte nel caso in cui stai utilizzando SOAPv2 in modalità non conforme a WSI).

tale condizione catena dovrebbe essere simile a questo:

// ... 
     if (property_exists($productData->additional_attributes, 'single_data')) { 
      foreach ($productData->additional_attributes->single_data as $_attribute) { 
       $_attrCode = $_attribute->key; 
       $productData->$_attrCode = $_attribute->value; 
      } 
     } 
     if (property_exists($productData->additional_attributes, 'multi_data')) { 
      foreach ($productData->additional_attributes->multi_data as $_attribute) { 
       $_attrCode = $_attribute->key; 
       $productData->$_attrCode = $_attribute->value; 
      } 
     } 
     else if (! property_exists($productData->additional_attributes, 'single_data')) { 
      foreach ($productData->additional_attributes as $key => $value) { 
       $productData->$key = $value; 
      } 
     } 
    // ... 

La terza condizione afferma che sia 'single_data' e 'multi_data' non sono proprietà di additional_attributes.


Anche se, a mio parere, il modo corretto per risolvere questo bug è quello di modificare il file "wsi.xml" in modo che sia coerente con wsdl.xml (o viceversa).

1

Utilizzo API SOAP per l'immissione di prodotti nei negozi Magento. qui è il codice completo

In caso di attributo personalizzato multiselezione.

   $arrProductTime = explode(',', '136,139'); 

       $result = $client->catalogProductCreate($session, 'simple', $attributeSet->set_id, 'product_sku1234', array(

        'categories' => array(36), 
        'websites' => array(1), 
        'name' => 'my_pdt1008', 
        'description' => 'my_pdt1', 
        'short_description' => 'my_pdt1000', 
        'weight' => '11', 
        'status' => '1', 
        'url_key' => 'product-url-key1', 
        'url_path' => 'product-url-path1', 
        'visibility' => '4', 
        'price' => '100', 
        'tax_class_id' => 1, 
        'meta_title' => 'Product meta title1', 
        'meta_keyword' => 'Product meta keyword1', 
        'meta_description' => 'Product meta description1', 
        'stock_data' => array('qty'=>'100','is_in_stock'=>1,'manage_stock'=>1), 
        'additional_attributes' => array('multi_data' => array(array('key' => 'product_time', 'value' => $arrProductTime))) 
       )); 
Problemi correlati