Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I create a product with additional attributes in Magento via Soap/Java

Good day!

I would like to use the Magento’s SOAP API to manage the product catalog, attributes etc. I'm running following configuration:-

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

In case someone wants to create a new product, it is necessary to set a few properties of the product object. Following code will demonstrate my approach to do this :

    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;
    }

I realized that I get an error written to the "system.log" of 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

I could localize the error in the "V2.php" file on line 265. According to the php.net documentation the "property_exists()" method only can check for fields in objects. As a matter of fact the "$productData" variable holds a property called "additional_attributes" which is of the type array. Therefore the execution of this code will lead to an error.

Moreover I don’t know to reproduce the object the structure of the "$productData" object through the use of Magento’s SOAP API V2.

If I examine this code ("foreach" loop) in line 270, it indicates that there is an object ("$productData") holding an array ("additional_attributes") which again shall encapsulate a set of key/value pairs (if I am right)

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

This seems to be a bug. So here is my question.

Am I going right to call this an programming issue which shall be posted in the bug base? Is there a way to get over this issue? Shall I rewrite parts of the php.code from above to satisfy my need to handle product information to create a product properly ?

Thanks in advance

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

the CatalogProductCreate-Call from the WSDL generated by 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>
like image 616
stereoscope Avatar asked Jan 22 '12 11:01

stereoscope


1 Answers

For the V2 SOAP API it appears that we need to nest the additional_attributes in a multi_data or single_data layer?

Looking at app/code/core/Mage/Catalog/Model/Product/Api/V2.php #256 I think we need to use

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

or

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

to be used like:

    $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();
    }
like image 124
creuzerm Avatar answered Nov 01 '22 18:11

creuzerm