Update products programmatically in Magento
Asked Answered
A

5

14

I'm working on a script that will create or update products in my catalog.
The script works fine when the product needs to be created, but it fails when the product already exists in the database giving me (many times) the following messages :

2011-09-30T08:00:53+00:00 ERR (3): Recoverable Error: Argument 3 passed to Mage_Catalog_Model_Resource_Eav_Mysql4_Abstract::_canUpdateAttribute() must be an array, null given, called in ...
2011-09-30T08:00:53+00:00 ERR (3): Recoverable Error: Argument 3 passed to Mage_Eav_Model_Entity_Abstract::_canUpdateAttribute() must be an array, null given, called in ...
2011-09-30T08:00:53+00:00 ERR (3): Warning: array_key_exists() [function.array-key-exists]: The second argument should be either an array or an object in ...

I've been looking at the method quoted in the message, but I can't find any reason why the script fails.
The script first try to load a product using :

$product = Mage::getModel('catalog/product')->loadByAttribute('sku', $sku);

and then test if the product was retrieved using a simple if(!$product) { //creation }.
All the code that follow the if statement is shared for creation or update and consists of setter calls on product object.

Here is the code I use :

$product = Mage::getModel('catalog/product')->loadByAttribute('sku', $sku);
if(!$product) {
    // the product doesn't exist yet
    $product = new Mage_Catalog_Model_Product();
    $product->setSku($sku);
    $product->setTypeId(Mage_Catalog_Model_Product_Type::TYPE_SIMPLE);
    $product->setCreatedAt(strtotime('now'));
}
// setters calls
$product->setTeinte(trim((string)$record->web_teinte));
// ...
// finally save the product
$product->save();

Maybe someone has already faced the same problem.
Any help is welcome ! Thank you.

Arresting answered 29/9, 2011 at 15:19 Comment(3)
Maybe we can help you if you'd post the relevant part of your script. Especially including the line causing the error, because at the moment only you know what instruction triggers the error.Batista
that's right, I'll edit the question. thank you.Arresting
I know the error comes with $product->save(); but I don't know why. When I log the product I see it is correctly loaded. I thought a simple call to the save() method would have made the updateArresting
S
25

Chances are, in your "setter calls" you are trying to set something that cannot be directly set on $product. It could even be the "setTeinte" as I am not sure what that is trying to set. But as we cannot see all your code, it is a little difficult to say, so as I guide, take a look at the code below, which sets some information directly on the product and then stock levels. It does therefore, illustrate how certain data has to be set. I hope it helps.

$SKU = (string)$XMLproduct->Sku;
$product = Mage::getModel('catalog/product')->loadByAttribute('sku',$SKU);

if ($product) {
    //Product found, so we need to update it in Magento.

    $product->setName((string)$XMLproduct->Name);
    $product->setPrice((real)$XMLproduct->SalePrice);
    //$product->setDescription((string)$XMLproduct->LongDescription);
    //$product->setShortDescription((string)$XMLproduct->Description);

    $product->save();

    $productId = $product->getId();
    $stockItem =Mage::getModel('cataloginventory/stock_item')->loadByProduct($productId);
    $stockItemId = $stockItem->getId();

    $stockItem->setData('manage_stock', 1);
    $stockItem->setData('qty', (integer)$XMLproduct->QtyInStock);

    $stockItem->save();

    echo $SKU," Updated: Name: '",(string)$XMLproduct->Name,"', Price: ",(real)$XMLproduct->SalePrice,", Stock level: ",$XMLproduct->QtyInStock,PHP_EOL;

    $updated++;
} 
Semipostal answered 30/9, 2011 at 9:7 Comment(5)
thank you for your answer. setTeinte is a call to set a string value for an attribute I created in the admin panel (and there many other calls like that). Reading your code really helped me to find out the solution. I was setting all those values as strings.. so I managed to type cast when needed and the update is ok. thank you.Arresting
do you have any idea where does these warnings come from ? the update is ok, but the messages still come in the log file....Arresting
I finally made the warning desappearing from the log by setting the store id before making the creation/update process (Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID));)...Arresting
Excellent, I am pleased that you have it working and glad my code helped you along the correct path.Semipostal
can u tell where did you place this script(the folder) and what's the naming convention?Quite
S
22

Adding Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID); before saving product solves the error. The sample code below updates product's cost.

Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
$productId = 160;
$newCost = 80;
$product = Mage::getModel('catalog/product')->load($productId);
$product->setCost($newCost)->save();
Seiler answered 12/9, 2013 at 7:27 Comment(1)
Thanks for your answer.it helped me to solve the issue.Frum
M
0

Easy with Magento API, also can use methods....

example

$data = array('qty'=>1, 'is_in_stock'=>1)

$stockModel = new Mage_CatalogInventory_Model_Stock_Item_Api;
$stockModel->update($product_id, $data);

Also can set Admin mode

Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
Mistrust answered 29/1, 2014 at 15:53 Comment(0)
D
0
//here what i use in codeigniter
function updateProducts(){
    $params = array('name' => 'adminhtml'); // frontend or adminhtml
    $this->load->library('magento', $params);
    error_reporting(E_ALL | E_STRICT);
    //$mageFilename = 'app/Mage.php';
    //require_once $mageFilename;
    Mage::setIsDeveloperMode(true);
    umask(0);
    Mage::app();
    Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID));      
    $obj = new stdClass(); 
    $obj->Sku = '25484684';
    $obj->Name = 'test product 2';
    $obj->SalePrice = 55;
    $obj->LongDescription = 'test product long decription.test product long decription.test product long decription.';
    $obj->Description = 'short descrption';
    $res = $this->updateMagentoProduct($obj);
    //dumb($res);
}
function updateMagentoProduct($XMLproduct){
    $SKU = (string)$XMLproduct->Sku;
    $product = Mage::getModel('catalog/product')->loadByAttribute('sku',$SKU);
    if (!$product) {//insert new product
        $product = Mage::getModel('catalog/product');
        $product->setSku($SKU);
    }       
    //$product = new Mage_Catalog_Model_Product();
    // Build the product
    $product->setAttributeSetId(4); // 4 means Default AttributeSet
    $product->setTypeId('simple');
    $product->setName((string)$XMLproduct->Name);
    $product->setCategoryIds(array(2,3,4,5,6,7));
    $product->setWebsiteIDs(array(1)); # Website id, 1 is default 
       //$product->setWebsiteIds(array(Mage::app()->getStore(true)->getWebsite()->getId()));
    //$product->setWebsiteIDs(array(1)); # Website id, my is 1 (default frontend)
    $product->setDescription((string)$XMLproduct->LongDescription);
    $product->setShortDescription((string)$XMLproduct->Description);
    $product->setPrice((real)$XMLproduct->SalePrice);
    # Custom created and assigned attributes
    //$product->setHeight('my_custom_attribute1_val');
    //$product->setWidth('my_custom_attribute2_val');
    //$product->setDepth('my_custom_attribute3_val');
    //$product->setType('my_custom_attribute4_val');
    //Default Magento attribute
    $product->setWeight(1.0);
        $product->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH);
    $product->setStatus(1);
    $product->setTaxClassId(0); # My default tax class
    /*$product->setStockData(array(
        'is_in_stock' => 1,
        'qty' => 99999
    ));*/
    $product->setCreatedAt(strtotime('now'));
    try {

        $product->save();
        $productId = $product->getId();
        $stockItem =Mage::getModel('cataloginventory/stock_item')->loadByProduct($productId);
        $stockItemId = $stockItem->getId();

        $stockItem->setData('manage_stock', 1);
        $stockItem->setData('qty', 99999);//(integer)$XMLproduct->QtyInStock

        $stockItem->save();



        echo '<h5>'.$SKU," Updated: Name: '",(string)$XMLproduct->Name,"', Price: ",(real)$XMLproduct->SalePrice,", Stock level: ",PHP_EOL.'</h5>';
    }
    catch (Exception $ex) {
        //Handle the error
        echo '<h5>'.$ex->getMessage().'</h5>';
    }
    // assign product to the default website        
    return $product->save();
}
Dissatisfy answered 25/3, 2014 at 12:15 Comment(0)
V
0
<?php
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
$product = Mage::getModel('catalog/product');

$product
//    ->setStoreId(1) //you can set data in store scope
    ->setWebsiteIds(array(1)) //website ID the product is assigned to, as an array
    ->setAttributeSetId(9) //ID of a attribute set named 'default'
    ->setTypeId('simple') //product type
    ->setCreatedAt(strtotime('now')) //product creation time
//    ->setUpdatedAt(strtotime('now')) //product update time

    ->setSku('testsku61') //SKU
    ->setName('test product21') //product name
    ->setWeight(4.0000)
    ->setStatus(1) //product status (1 - enabled, 2 - disabled)
    ->setTaxClassId(4) //tax class (0 - none, 1 - default, 2 - taxable, 4 - shipping)
    ->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH) //catalog and search visibility
    ->setManufacturer(28) //manufacturer id
    ->setColor(24)
    ->setNewsFromDate('06/26/2014') //product set as new from
    ->setNewsToDate('06/30/2014') //product set as new to
    ->setCountryOfManufacture('AF') //country of manufacture (2-letter country code)

    ->setPrice(11.22) //price in form 11.22
    ->setCost(22.33) //price in form 11.22
    ->setSpecialPrice(00.44) //special price in form 11.22
    ->setSpecialFromDate('06/1/2014') //special price from (MM-DD-YYYY)
    ->setSpecialToDate('06/30/2014') //special price to (MM-DD-YYYY)
    ->setMsrpEnabled(1) //enable MAP
    ->setMsrpDisplayActualPriceType(1) //display actual price (1 - on gesture, 2 - in cart, 3 - before order confirmation, 4 - use config)
    ->setMsrp(99.99) //Manufacturer's Suggested Retail Price

    ->setMetaTitle('test meta title 2')
    ->setMetaKeyword('test meta keyword 2')
    ->setMetaDescription('test meta description 2')

    ->setDescription('This is a long description')
    ->setShortDescription('This is a short description')

    ->setMediaGallery (array('images'=>array (), 'values'=>array ())) //media gallery initialization
    ->addImageToMediaGallery('media/catalog/product/1/0/10243-1.png', array('image','thumbnail','small_image'), false, false) //assigning image, thumb and small image to media gallery

    ->setStockData(array(
                       'use_config_manage_stock' => 0, //'Use config settings' checkbox
                       'manage_stock'=>1, //manage stock
                       'min_sale_qty'=>1, //Minimum Qty Allowed in Shopping Cart
                       'max_sale_qty'=>2, //Maximum Qty Allowed in Shopping Cart
                       'is_in_stock' => 1, //Stock Availability
                       'qty' => 999 //qty
                   )
    )

    ->setCategoryIds(array(3, 10)); //assign product to categories
$product->save();
Veinule answered 24/3, 2017 at 7:27 Comment(1)
Please justify your answer, and explain how the code you provide works. This will help the OP understand better.Xyster

© 2022 - 2024 — McMap. All rights reserved.