Creating Magento products from a script
07 Oct 2009, by Peter Spiller
8 Comments · Posted in Magento

    Magento allows several different ways to add products to the catalog, including manual editing, upload via spreadsheet and the web services Magento Core API. For developers who want to add products through PHP however, there are a few caveats to be aware of for the product to be displayed on the frontend.

    The basics of adding a new product are trivial - you get a new copy of the appropriate model, fill in the details and call the save() method:

    $product = Mage::getModel('catalog/product');
    $product->setName("Type 7 Widget");
    $product->setDescription("This widget will give you years of trouble-free widgeting.");
    $product->setShortDescription("High-end widget.");
    $product->setAttributeSetId(9); // need to look this up
    $product->setCategoryIds("20,24"); // need to look these up
    $product->setTaxClassId(2); // taxable goods
    $product->setVisibility(4); // catalog, search
    $product->setStatus(1); // enabled
    // assign product to the default website

    The example above shows a minimal set of attributes you should be setting on a new product. If you run this code and look under Manage Products on the backend, you should see your new product. However, the real trick is making sure they appear on the frontend.

    First of all, you need to make sure you set the product's visibility to something that includes 'catalog' (2 is catalog only, 4 is catalog and search results) and the product's status must be set to enabled (1). If you want the product to appear in one or more categories (which you usually do), the product's category IDs must be set correctly. Note that the setCategoryIds() function takes a comma-separated string of category IDs, not an array. A category's ID can be found by viewing it in the Manage Categories screen on the backend. The product's attribute set ID should also be defined. You can get attribute set IDs by checking the URLs in Manage Attribute Sets (i.e. if the link to edit the 'Default' attribute set is admin/catalog_product_set/edit/id/4/, then its ID is 4).

    Even once all these settings are complete, the product will almost certainly not appear on the frontend. One other attribute must be set - the websites the product belongs to. This even has to be set if your Magento installation doesn't use multiple websites. The setWebsiteIds() line above assigns the product to the default website, which is sufficient for a single-website setup. Note that this method uses an array, unlike setCategoryIds().

    The product should now be appearing on the frontend, but it will probably be showing up as 'Out of stock'. A product's inventory and stock options are contained in a separate object, rather than as part of the product itself. Adding the following code somewhere between the getModel() and save() lines will allow you to set the stock data:

    $stockData = $product->getStockData();
    $stockData['qty'] = 10;
    $stockData['is_in_stock'] = 1;
    $stockData['manage_stock'] = 1;
    $stockData['use_config_manage_stock'] = 0;

    This code gets the product's stock and inventory options as an array, modifies them and then saves the array back to the object. The options should be self-explanatory - the important one is 'is_in_stock', which controls whether the product is in stock or not. The example above sets the product's 'Manage Stock' attribute to 'Yes' and un-ticks the corresponding 'Use Config Settings' checkbox, so the product will always track stock regardless of the global config setting. This is just an example, so be sure to set values appropriately for your store.

    Creating products from a script is quite easy, and using the internal Magento API can be faster and a lot more flexible than using the web services Magento Core API or an import profile and CSV file.


    Any idea how to then add this product to a pre-existing product group?
    Comment by Allan - 2 Nov 2009 11:23:42 PM
    Thanks!!! Precisely what I needed to import the x-thousand products from the xml file into Magento! Especially the stockData -part was very helpfull! To add my simple products to a (existing) configurable I then used some direct SQL statements to insert the links into the category_product_super_xx.. tables which worked fine. Thanks again :-)
    Comment by Isolde - 10 Nov 2009 2:01:41 AM
    Its really useful post. Thanks to fontis
    Comment by Sundar - 6 Feb 2010 7:33:51 AM
    This is great! This was the perfect first step for writing a product import script for me, so thanks a lot for sharing it!

    Word of advice: This script will not support updates to existing products! If you want to do so, you can load the existing product with `$mageProduct->load([some product id])`. If you've only got the sku, you can get the product ID by calling `$mageProduct->getIdBySku($sku)`. If you get the "invalid argument in foreach()" error when updating a product it's because you have the store set incorrectly; you can only update products through the admin store. You can set the app to use the admin store with `Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID)`, but this example uses the current store to find the WebsiteID, so you have to set that manually now with `$mageProduct-setWebsiteIds(array(1))` or whatever the website IDs of your store are. I had no idea so I just made a product and printed it with print_r since I can never figure out where these constants are coming from.

    Has anybody figured out how to script custom attributes? That one seems to be escaping me so far.
    Comment by Jordan - 28 May 2010 11:54:27 PM
    Scripting Custom Attributes:
    create an attribute in the admin panel
    assign the attribute to an attribute set
    use $prod->setAttributeSetId($some_id) to assign the product to the proper attribute set. The only way I saw to get the right attribute set ID is to open it in the admin screen and look at the URL. Pretty lame but it works.
    Whatever you set the attribute key to can be used in your code. I have a foreign_sku attribute that I set like this:

    I probably spent about three hours searching around for it before I just tried what looked like the dumbest thing possible, and it worked.
    Comment by Jordan - 15 Jun 2010 6:11:25 AM
    Regarding the comment that setCategoryIds() requires a comma separated list of category ID's and not an array - in Magento (at least) both are acceptable. Internally the setCategoryIds() method checks to see if the categories passed in are a string and if they are it explodes them on a comma.

    Therefore, these are both equivalent:

    $product->setCategoryIds( '1,2,3,4,5' );
    $product->setCategoryIds( array( 1, 2, 3, 4, 5 ) );


    - Bob -
    Comment by Bob Brown - 17 Aug 2010 8:49:23 PM
    What about image add??
    Comment by Neetha - 20 Aug 2010 9:37:40 PM
    use this script to add image. it works with loop too.

    $product->addImageToMediaGallery(Mage::getBaseDir('media') . DS . 'import' . trim("/a/_/a.png"), NULL, false, false);
    Comment by Anonymous - 7 Jan 2011 3:28:58 AM
    Comments are closed for this post