This isn’t ground-breaking code, but rather just using some core code in a rather stripped out manner. As we’re not big fans of Magento data flow here, we perform most of our stock and catalogue updates using external scripts to Mage::app. We have been trickling elements of these out to the wider world so you can also benefit from them.
Managing large catalogues and updating stock levels regularly can be mission impossible in Magento, but not any more. With this script – we processed 120,000 stock updates in the blink of an eye. Next time we’ll teach you how to import products at 0.7 seconds each …
-
1
Create a CSV with a minimum of 2 columns, the SKU and any of the following,qty min_qty use_config_min_qty is_qty_decimal backorders use_config_backorders min_sale_qty use_config_min_sale_qty max_sale_qty use_config_max_sale_qty is_in_stock use_config_notify_stock_qty manage_stock use_config_manage_stock stock_status_changed_automatically type_id
Then save it to ./app/var/import/updateStockLevels.csv. For examples sake, we will use,
"sku","qty" "prod1","11"
-
2
Copy the code below into a new file, ./quick_updateStock.php<? define('MAGENTO', realpath(dirname(__FILE__))); require_once MAGENTO . '/app/Mage.php'; umask(0); Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID); $count = 0; $file = fopen(MAGENTO . '/var/import/updateStockLevels.csv', 'r'); while (($line = fgetcsv($file)) !== FALSE) { if ($count == 0) { foreach ($line as $key=>$value) { $cols[$value] = $key; } } $count++; if ($count == 1) continue; #Convert the lines to cols if ($count > 0) { foreach($cols as $col=>$value) { unset(${$col}); ${$col} = $line[$value]; } } // Check if SKU exists $product = Mage::getModel('catalog/product')->loadByAttribute('sku',$sku); if ( $product ) { $productId = $product->getId(); $stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($productId); $stockItemId = $stockItem->getId(); $stock = array(); if (!$stockItemId) { $stockItem->setData('product_id', $product->getId()); $stockItem->setData('stock_id', 1); } else { $stock = $stockItem->getData(); } foreach($cols as $col=>$value) { $stock[$col] = $line[$value]; } foreach($stock as $field => $value) { $stockItem->setData($field, $value?$value:0); } $stockItem->save(); unset($stockItem); unset($product); } echo "<br />Stock updated $sku"; } fclose($file); ?>
-
3
Visit the file above in your browser, or via command line. It runs very quickly (approx 0.03 seconds per product), so don’t be too surprised if its over quickly!
Pete
18 Feb. 2011
Great script – If you want to update prices or any other atribute for that matter change
$stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($productId);to
$stockItem = Mage::getSingleton("catalog/Product")->load($productId);It’s slower, but does the trick
Jason
8 Mar. 2011
Pete, do you see the behavior of the product special price etc getting corrupted if they are not explicitly set using
$stockItem = Mage::getSingleton(“catalog/Product”)->load($productId);
nar
16 May. 2011
I had this issue. Special prices were set to zero after modifying the script this way.
AMP
18 Jul. 2011
I am not sure why you would do this anyway, as you can set other data utilising the $product object and you don’t slow the script down any. (or am I missing something?)
For example, change the product name:
$product->setName("new product name");You do, of course, have to also save the $product object with:
$product->save();Works for me.
Benjamin
21 Jul. 2011
We’re all aware of this, but we are not setting product data – we are setting product STOCK levels – its a different model.
On a sidenote, loading and saving the product model has significant overheads – so whilst convenient and quick to code – its by far the slowest method to modify product attributes.
Kevin Giles
25 Feb. 2011
Please could someone post an actual piece of XML which shows the layout for updating a single product stock qty. Not everyone uses PHP!
I have this much but don’t understand the sub-format for defining that I want to update qty field. Perhaps I have missed this in the magento on-line docs.
I want to test the XML in SOAPUI.exe .
Thanks.
Kevin
Benjamin
25 Feb. 2011
This method intentionally doesn’t use Data Flow (which I am assuming you are referring to when talking about XML upload profiles) or Web Services. Data Flow is SLOW, hence the use of this script. If you are looking to change status by web services, look here http://www.magentocommerce.com/wiki/doc/webservices-api/introduction
It can be tweaked to use XML instead of CSV, its not really a large amount of work, get in touch if you are interested.
Kevin Giles
25 Feb. 2011
Sorry – when I said “This much” I meant:-
d0c88544d5b3f8e76172656591dabb05
cataloginventory_stock_item.update
product_id
164
plus the normal header stuff.
Giuseppe Barbiero
20 May. 2011
Hi guis and thanks for nice snippet
this idea is very clear congratulations
I have an only problem. Calling directly the file like you say to execute it I cannot bypass the magento router , so the file is not found
I come from joomla where this problem doesn’t exit. May you help me on how to call this file directly if it’s saved inside same Magento Folder?
thanks
Giuseppe
20 May. 2011
Hi I am an outcoming virtuemart user who want to pass to magento cart
I am testing your snippet, and many many thanks for your effort, this is a nice functionality
If I am right, the script to update stock should be placed in the same root folder of Magento.
I am trying it on the 1.5.0 version and the result is it loops many many times until the max execution time is reached, and then it stops.
The csv is made of one line only to test.
Do you know why it may fails? I need thie feature so much (everyone I think they need ) as modiftying stock in magento is really tedious
Thanks
Giuseppe
20 May. 2011
Ok I found the error of the loop
I put csv file inside app/var/import, but this is not correct, i should have put it inside the var folder
Thanks and sorry to bother
Rachita
24 May. 2011
Other than our agency updating the usual stuff on a Magento, can I update them at the back-end for some urgencies too?
How much time does it take for an updation to reflect on the website – i. instant ii. is it time-consuming
Benjamin
24 May. 2011
Speed will be platform dependant, try it for yourself!
John
13 Jun. 2011
Awesome script. As I look at this, I think that Magento’s API should be abandoned in favor of short scripts such as this. I take it this is your experience? I’m asking as I am new to Magento (not programming) and it is incredible how slow the API is!
Tim Thurlow
17 Jun. 2011
This is the best solution by far if you also want to update is_in_stock so that out of stock items don’t appear on your site. It’s also very fast. Thanks
pepper
23 Jun. 2011
I have the same problem with Tim Thurlow. The script updates quantities but not the “is_in_stock” parameter. That way the products are always available, even if the stock quantity is set to 0.
Matthew Galvin
12 Jul. 2011
I’ve found that SOAP calls and Mage.php calls are noticeably slower than direct database updates. The downside, is that doing direct database updates also require an API-based re-index at the end. I usually just throw this in to the function destruct to re-index at the end.
The database takes a little while to reverse engineer, but there are some capable tools out there.
Benjamin
20 Aug. 2011
We do a lot of direct DB queries for stock/product import etc., the overheads of using the native models are sometimes too much for big/frequent jobs.
Mitch
20 Aug. 2011
Nope not working for me any help here, someone I can contact?
Would be brilliant to get this working as we have a lot of skus at the moment and its taking about 8 hours yet we have far fewer then your quoted 120k
Benjamin
20 Aug. 2011
Sure you can, go to the contact page.
Just remember, speed will be platform dependant, run it on a slow/poorly set up server – and it will be slow.
Mitch
20 Aug. 2011
Does the CSV file need to have quotation marks for each field?
Mitch
20 Aug. 2011
Don’t worry got it to work with a couple of tweaks
Thanks
Bill Kellaway
26 Aug. 2011
Brilliant, exactly what I needed. Thanks !!!
André
1 Sep. 2011
Hi, i have been using this with no problems, and its very very useful.
Now that we have more than 6000 products to update, the server is timing out the function. Can i split the update into two functions until i do not find a better server? Can someone help me wiht that? Thank you.
Benjamin
1 Sep. 2011
6,000 products shouldn’t be an issue at all.
Your time-outs are because your server hasn’t been set up properly for Magento – get in touch with our team at http://www.sonassihosting.com for truly optimised Magento dedicated servers.
Bishar
19 Sep. 2011
Great script! Just one request, can someone help me map the columns to different headings please? For eg. ‘sku’ = “Product Code”
Marcus Powell
26 Sep. 2011
Hi thanks for the script.
I have a quick question. On my magento test server (shared hosting). This script runs very quick. On my live VPS however it crawls. At it’s current rate it would of imported about a thousand records in an hour.
From debugging your code; it seems the slow down on my live server is caused by this line -> $stockItem->save(); Taking this out and the script runs fine.
Any ideas why this would cause such a slow down issue on the VPS?
Many Thanks,
Marcus
Benjamin
27 Sep. 2011
Its not much of a surprise. A VPS is a less than ideal environment for running Magento – you’re trying to run all your services in a tiny set up (mysql/dns/web/email), whereas with shared, although contended, you’re likely to have more in the way of “burstable” resources.
Our shared hosting (www.sonassihosting.com), would outperform any VPS of similar price by quite a margin.
Marcus Powell
27 Sep. 2011
Thanks for the info. I will certainly bear you in mind once the hosting runs out for this year.
I think, in this case it might be down to Google Shopping though. It saves to the database locally and then uses the Google Shopping API to update prices there.
Also if I used the price update line
:
$stockItem = Mage::getSingleton(“catalog/Product”)->load($productId);
My price updates, but the categories my products are in get jumbled up. Not good on 2000 products
Any ideas why?
I am using Magneto 1.5.0.1
Stuart
11 Oct. 2011
After you run this script do you need to reindex the data, I have been experimenting with using MAGMI for stock updates but we have a very large catalog (up to 800K items) and a few people are saying reindexing after an update will take substantially longer than the update itself.
Judder
28 Oct. 2011
It’s good to check that the script actually finds the stock file you feed it (if you put one in a different place as I did) so you can do this with an initial check, otherwise every value is NULL and nothing of course works :->
Rajib
17 Nov. 2011
Great script!, I have tested in my website and it works like a charm, I have a question, I get XML feed of all active products only , which I will convert to csv and store in var/import folder, as the daily feed contains only active products i need to update all products qty=0 and is_in_stock=0 before running the script.
direct query to DB will do ?
update cataloginventory_stock_item set qty=0, is_in_stock=0
any help is appreciated
Thank you
Tony
27 Nov. 2011
Anyone have luck running this with v 1.6.1.0? I had it running perfect on 1.5.1, when I upgraded to 1.6.1.0 it will run but doesnt update the stock.
cosset
6 Dec. 2011
WELL DONE PEOPLE!!!!!!! thank you so so so so much for this! it’s great, i have an website with over 20k products and with the standard magento import tools it took me over 12 hours to update the stock and price, but with this…when the updating day is coming there are no worries
. THANK YOU!
M van Dongen
10 Dec. 2011
Lifesaver
Luc
6 Jan. 2012
Well done! Integrated this code into my code that generates the stock outputfile from another back-office system. Much faster than the regular import capabilties of Magento.
Luc
6 Jan. 2012
One question? Why not read the total file in memory and then do the update? Should increase the performance a bit more with al lot of products. Now lines are read and processed one by one….
drooped
9 Jan. 2012
hi
when im using this script for my price update all of empty field are changed to “0″
can you help me for this?????
tnx
Douglas Scott
13 Jan. 2012
Does anyone know how to map the sku and qty to different headings within the csv since the stock update file comes from a third party each morning? Thanks!
Josep Mª Puig
31 Jan. 2012
It doesn’t work for me in my store using magento 1.6.1 .
;(
Cosset
9 Feb. 2012
Hello,
I’ve try this and it works perfect for a while, but now I receive Fatal error: Maximum execution time of 30 seconds exceeded in…The hosting provider says that they didn’t change anything, I didn’t change anything, but the script does not work anymore (only 800 SKU’s at a time) Can you please help?
Thank you,
Benjamin
9 Feb. 2012
If it was working, and now its not – it’ll be your host
Try switching to a Magento hosting provider … we are taking on new customers at the moment starting at £30 per month.