Create Multiple Products in Magento - magento

I'm working on magento using Magento 1.X API. I want to create products in magento so I'm using catalogProductCreate method to create.
This is working great when it is around 5 to 10 products, but when trying to insert multiple products it is taking a lot of time.
Is there any method to insert bulk products at a time.

The API/programmatic/dataflow method of adding products in Magento is notoriously slow when dealing with large data sets.
If you haven't already looked at it, try Magmi - it is the missing piece of Magento catalogue management. You can add/update thousands of products in minutes with spreadsheets. It can also be called on CLI which opens up lots of excellent automation possibilities.
Oh, and best of all - it's free.
https://github.com/dweeves/magmi-git

I've been using this code to add/update products on Magento.
<?php
include_once("app/Mage.php");
Mage::app();
umask(0);
Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID));
$counter = 0;
I have this function to get (or create) a product by SKU:
function GetProduct($sku)
{
global $counter;
echo $sku;
$p = Mage::getModel('catalog/product');
$productId = $p -> getIdBySku($sku);
if($productId)
{
echo "!";
$p -> load( $productId );
}
else
{
$p->setTypeId('simple');
$p->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH);
$p->setStatus(1);
$p->setTaxClassId(7);
$p->setWebsiteIDs(array(1));
$p->setStoreIDs(array(1));
$p->setAttributeSetId(4);
$p->setSku($sku);
}
echo "...";
$counter++;
echo " ".$counter;
return $p;
}
Here's the function to save the product:
function SaveProduct($p)
{
try
{
if (is_array($errors = $p->validate()))
{
$strErrors = array();
foreach($errors as $code=>$error)
{
$strErrors[] = ($error === true)? Mage::helper('catalog')->__('Attribute "%s" is invalid.', $code) : $error;
echo $strErrors[0];
}
$this->_fault('data_invalid', implode("\n", $strErrors));
}
$p->save();
echo "\n";
}
catch (Mage_Core_Exception $e)
{
$this->_fault('data_invalid', $e->getMessage());
}
}
And finally I'm calling like this:
$product = GetProduct('sku1');
$product->setData('thumbnail_label', 'sku1');
SaveProduct($product);
unset($product);
$product = GetProduct('sku2');
$product->setData('url_path', 'plastic-hat.html');
SaveProduct($product);
unset($product);
$product = GetProduct('sku3');
$product->setData('thumbnail_label', 'sku3');
SaveProduct($product);
unset($product);
$product = GetProduct('sku4');
$product->setData('thumbnail_label', 'sku4');
SaveProduct($product);
unset($product);
$product = GetProduct('sku5');
$product->setData('thumbnail_label', 'sku5');
SaveProduct($product);
unset($product);
I run this code from the command-line as there is a memory leak running it this way. You can only get so many products updated before it blows the memory and you have to edit and re-run the code to keep going, but it works and it's relatively fast.

Related

Magento - Should I do mass update about 5k in mid night or separate multiple times in a day

I'm using magento EE 1.14.2.1.I have about 50k products in databases.I just want some useful advice about updating products.
As I mentioned in title , in everyday I have about 5k product need to be update stock and price.So,should I do it in midnight then reindex them all in one time or turn on the enterprise refresh index cron and update product in many times in a day ( about 100 product per times ).The most important thing which I concerted is the website performance and avoiding MySQL deadlock.
Here's an option for you. I have an import.php script that I use to import or update large numbers of products and their attributes. It will let you either update or create a product based on SKU. You would have to check the constants to see if they match your Magento.
This is a script for Community Edition so you would have to test for Enterprise.
<?php
include_once("app/Mage.php");
Mage::app();
umask(0);
Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID));
$counter = 0;
function GetProduct($sku)
{
global $counter;
echo $sku;
$p = Mage::getModel('catalog/product');
$productId = $p -> getIdBySku($sku);
if($productId)
{
echo "!";
$p -> load( $productId );
}
else
{
$p->setTypeId('simple');
$p->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH);
$p->setStatus(1);
$p->setTaxClassId(7);
$p->setWebsiteIDs(array(1));
$p->setStoreIDs(array(1));
$p->setAttributeSetId(4);
$p->setSku($sku);
}
echo "...";
$counter++;
echo " ".$counter;
return $p;
}
function SaveProduct($p)
{
try
{
if (is_array($errors = $p->validate()))
{
$strErrors = array();
foreach($errors as $code=>$error)
{
$strErrors[] = ($error === true)? Mage::helper('catalog')->__('Attribute "%s" is invalid.', $code) : $error;
echo $strErrors[0];
}
$this->_fault('data_invalid', implode("\n", $strErrors));
}
$p->save();
echo "\n";
}
catch (Mage_Core_Exception $e)
{
$this->_fault('data_invalid', $e->getMessage());
}
}
$product = GetProduct('SKU01'); $product->setData('upc', '013051388461'); SaveProduct($product); unset($product);
$product = GetProduct('SKU02'); $product->setData('special_price', null); $product->setData('special_from_date', null); SaveProduct($product); unset($product);
$product = GetProduct('SKU03'); $product->setData('cardboard_height_cm', 28.5); $product->setData('cardboard_width_cm', 37); SaveProduct($product); unset($product);
?>
I often get Excel to create the lines like $product = GetProduct('SKU03'); $product->setData('cardboard_height_cm', 28.5); $product->setData('cardboard_width_cm', 37); SaveProduct($product); unset($product); and then just copy and paste into the script. I can edit before running.
This is much faster than importing a CSV and it calls all of the correct observers.
Just run this from a SSH shell.

Magento can not add product programmatically

i have use below code to add product in magento but not success ,anyone know how to do?
code here
code txt file
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));
$product = new Mage_Catalog_Model_Product();
$product->setSku('A123');
$product->setAttributeSetId(4);
$product->setTypeId('simple');
$product->setName('Some cool product name');
$product->setCategoryIds(array(19));
$product->setWebsiteIDs(array(1));
$product->setDescription('Full description here');
$product->setShortDescription('Short description here');
$product->setPrice(39.99);
$product->setWeight(4.0000);
$product->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH);
$product->setStatus(1);
$product->setTaxClassId(0);
$product->setStockData(array(
'is_in_stock' => 1,
'qty' => 99999
));
$product->setCreatedAt(strtotime('now'));
try {
$product->save();
}
catch (Exception $ex) {
}
?>
i hope it may bemage.php path issue.Try put proper of mage file path
Suppose,My Magento path is /home/abc/www/www/ in server.
and my script file location location in /home/abc/www/www/try/dot/myscript.php
If you try to include mage.php from myscript.php then
$mageFilename = '/home/abc/www/www/app/Mage.php'
or
$mageFilename = '../../app/Mage.php'
i have run your script with modify mage.php file location call in script.it is works
I've been using this code to add/update products on Magento.
<?php
include_once("app/Mage.php");
Mage::app();
umask(0);
Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID));
$counter = 0;
I have this function to get (or create) a product by SKU:
function GetProduct($sku)
{
global $counter;
echo $sku;
$p = Mage::getModel('catalog/product');
$productId = $p -> getIdBySku($sku);
if($productId)
{
echo "!";
$p -> load( $productId );
}
else
{
$p->setTypeId('simple');
$p->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH);
$p->setStatus(1);
$p->setTaxClassId(7);
$p->setWebsiteIDs(array(1));
$p->setStoreIDs(array(1));
$p->setAttributeSetId(4);
$p->setSku($sku);
}
echo "...";
$counter++;
echo " ".$counter;
return $p;
}
Here's the function to save the product:
function SaveProduct($p)
{
try
{
if (is_array($errors = $p->validate()))
{
$strErrors = array();
foreach($errors as $code=>$error)
{
$strErrors[] = ($error === true)? Mage::helper('catalog')->__('Attribute "%s" is invalid.', $code) : $error;
echo $strErrors[0];
}
$this->_fault('data_invalid', implode("\n", $strErrors));
}
$p->save();
echo "\n";
}
catch (Mage_Core_Exception $e)
{
$this->_fault('data_invalid', $e->getMessage());
}
}
And finally I'm calling like this:
$product = GetProduct('sku1');
$product->setData('thumbnail_label', 'sku1');
SaveProduct($product);
unset($product);
$product = GetProduct('sku2');
$product->setData('url_path', 'plastic-hat.html');
SaveProduct($product);
unset($product);
$product = GetProduct('sku3');
$product->setData('thumbnail_label', 'sku3');
SaveProduct($product);
unset($product);
$product = GetProduct('sku4');
$product->setData('thumbnail_label', 'sku4');
SaveProduct($product);
unset($product);
$product = GetProduct('sku5');
$product->setData('thumbnail_label', 'sku5');
SaveProduct($product);
unset($product);
I run this code from the command-line as there is a memory leak running it this way. You can only get so many products updated before it blows the memory and you have to edit and re-run the code to keep going, but it works and it's relatively fast.
You should be able to slot your code in quite nicely.

Magento get last added products options in cart

I am using ajax to add products to cart.when New product added to cart i want to display its details on right sidebar. I am able to list simple product, but i am not able to display bundle product options.I used following code to display cart items to right sidebar
$cartItems = Mage::getSingleton('checkout/session')->getQuote()->getAllVisibleItems();
foreach($cartItems as $item){
echo $item->getName();
}
Try this code:
$cartItems = Mage::getSingleton('checkout/session')->getQuote()->getAllVisibleItems();
foreach($cartItems as $item){
$result = array();
// Load the configured product options
$options = $item->getProduct()->getTypeInstance(true)->getOrderOptions($item->getProduct());
// Check for options
if ($options)
{
if (isset($options['options']))
{
$result = array_merge($result, $options['options']);
}
if (isset($options['additional_options']))
{
$result = array_merge($result, $options['additional_options']);
}
if (!empty($options['attributes_info']))
{
$result = array_merge($options['attributes_info'], $result);
}
}
$finalResult = array_merge($finalResult, $result);
}
I think, it can help you.

How do I get the options for bundled products on the success page?

On the success page, I have no trouble getting a list of the products purchased with the following code:
$order = Mage::getModel('sales/order')->loadByIncrementId($this->getOrderId());
foreach ($order->getAllItems() as $item){
$subtotal = number_format($item->getSubtotal(),2);
}
What I can't figure out, is how to get an object or an array of the options for bundled products. These are standard options like what color a product is.
I have not specifically tried this with bundled products, but the code below works with configurable products, and I'm sure you can modify it as needed to fit your situation.
$order = Mage::getModel('sales/order')->loadByIncrementId($this->getOrderId());
foreach ($order->getAllItems() as $item){
$productOptions = $item->getProductOptions();
if (isset($productOptions['attributes_info'])) {
foreach ($productOptions['attributes_info'] as $productOption) {
echo $label = $productOption['label'];
echo '<br />';
echo $value = $productOption['value'];
}
}
}
My suggestion is to start broad (i.e. at the $item level), see what Magento returns (using Zend_Debug::dump($item->getData()), and then work your way down to what you need.
Hope that helps.

Magento programmatically remove product images

This must be a such a simple programming task that I absolutely cannot find any information about it on the net. Basically, I'm trying to DELETE product images. I want to delete all images from a product's media gallery. Can I do this without wading through a million lines of code for such a simple task?
Please note that I've already tried this:
$attributes = $product->getTypeInstance()->getSetAttributes();
if (isset($attributes['media_gallery'])) {
$gallery = $attributes['media_gallery'];
$galleryData = $product->getMediaGallery();//this returns NULL
foreach($galleryData['images'] as $image){
if ($gallery->getBackend()->getImage($product, $image['file'])) {
$gallery->getBackend()->removeImage($product, $image['file']);
}
}
}
This absolutely does not work. I'm trying to delete images during an import so that I do not keep accruing duplicates. Any help would be greatly appreciated.
Okay, this is how I finally fixed my problem.
if ($product->getId()){
$mediaApi = Mage::getModel("catalog/product_attribute_media_api");
$items = $mediaApi->items($product->getId());
foreach($items as $item)
$mediaApi->remove($product->getId(), $item['file']);
}
This is the link that finally set my head straight: http://www.magentocommerce.com/wiki/doc/webservices-api/api/catalog_product_attribute_media
Too bad it's not as simple as $product->getImages(), eh?
In Magento 1.7.0.2 I use this code for remove all images from a product gallery:
//deleting
Mage::app()->getStore()->setId(Mage_Core_Model_App::ADMIN_STORE_ID);
$mediaApi = Mage::getModel("catalog/product_attribute_media_api");
$items = $mediaApi->items($product->getId());
$attributes = $product->getTypeInstance()->getSetAttributes();
$gallery = $attributes['media_gallery'];
foreach($items as $item){
if ($gallery->getBackend()->getImage($product, $item['file'])) {
$gallery->getBackend()->removeImage($product, $item['file']);
}
}
$product->save();
With code from Davids Tay answer, I got the error:
Fatal error: Uncaught exception ‘Mage_Eav_Model_Entity_Attribute_Exception’ with message ‘SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (base_xxx.catalog_product_entity_media_gallery_value, CONSTRAINT FK_CAT_PRD_ENTT_MDA_GLR_VAL_VAL_ID_CAT_PRD_ENTT_MDA_GLR_VAL_ID FOREIGN KEY (value_id) REFERENCES `catalog_prod)’
To remove all images from a product gallery:
$product = Mage::getModel('catalog/product')->load($id);
$mediaGalleryAttribute = Mage::getModel('catalog/resource_eav_attribute')->loadByCode($entityTypeId, 'media_gallery');
$gallery = $product->getMediaGalleryImages();
foreach ($gallery as $image)
$mediaGalleryAttribute->getBackend()->removeImage($product, $image->getFile());
$product->save();
During deleting of images I found one interesting thing. When you try this code:
$galleryData = $product->getMediaGallery(); //this returns NULL
Media gallery object depends on how your product was created, if:
$product = Mage::getModel('catalog/product')->loadByAttr('sku', $sku);
then media gallery will be empty, if:
$product = Mage::getModel('catalog/product')->load($id);
then media gallery is object and you can use this object to delete images from db.
To delete images from file system you have to add such code:
#unlink(Mage::getBaseDir('media') . '\catalog\product\' . $image['file']);
but if you want to change image and name it like previous image (image1.png replace with image1.png) in this case you will have browser caching issue.
Also you can try to load media gallery for product:
$product->getResource()->getAttribute('media_gallery')->getBackend()->afterLoad($product);
This is the code I finally decided to use for this task.
protected function _removeMediaGalleryImages(Mage_Catalog_Model_Product $product)
{
$mediaGalleryData = $product->getMediaGallery();
if (!isset($mediaGalleryData['images']) || !is_array($mediaGalleryData['images'])) {
return;
}
$toDelete = array();
foreach ($mediaGalleryData['images'] as $image) {
$toDelete[] = $image['value_id'];
}
Mage::getResourceModel('catalog/product_attribute_backend_media')->deleteGallery($toDelete);
}
Hopefully this answer isn't unwelcome, as it's technically not a solution achieved via Magento programming as you ask, but I have successfully purged all gallery images myself for the same purpose simply by truncating the relevant tables in Magento 1.4.2.0 (I believe it's the same table structure in 1.5 as well).
TRUNCATE TABLE `catalog_product_entity_media_gallery`
TRUNCATE TABLE `catalog_product_entity_media_gallery_value`
Then follow up by removing all the image files within the /media/catalog/product directory.
I did look for a way to do this programmatically myself, but found this much more efficient and have experienced no negative side effects.
Just use this code to create .php file and place it to root folder of magento.
<?php
require_once 'app/Mage.php';
Mage::app();
Mage::app()->getStore()->setId(Mage_Core_Model_App::ADMIN_STORE_ID);
$products = Mage::getModel('catalog/product')->getCollection();
//->addAttributeToFilter('entity_id', array('gt' => 14000));
$mediaApi = Mage::getModel("catalog/product_attribute_media_api");
foreach($products as $product) {
$prodID = $product->getId();
$_product = Mage::getModel('catalog/product')->load($prodID);
$items = $mediaApi->items($_product->getId());
foreach($items as $item) {
$mediaApi->remove($_product->getId(), $item['file']);
}
}
?>
What About this
Mage::app()->getStore()->setId(Mage_Core_Model_App::ADMIN_STORE_ID);
$mediaApi = Mage::getModel("catalog/product_attribute_media_api");
$items = $mediaApi->items($product->getId());
$attributes = $product->getTypeInstance()->getSetAttributes();
$gallery = $attributes['media_gallery'];
foreach($items as $item){
if ($gallery->getBackend()->getImage($product, $item['file'])) {
$gallery->getBackend()->removeImage($product, $item['file']);
}
}
$product->save();
Fastest way to remove image,then follow below steps:
delete all records from
catalog_product_entity_media_gallery
catalog_product_entity_media_gallery_value'
table because magento is save all product image data at those table.
Then index from Index management from admin for set image black.
Then remove image from dir then goto Your magento dir at media/catalog/product and from this folder delete all file.
Another Process:
Andy Simpson,you need a script which is delete all product from your system which will delete from DB and file system.
Step1: Create a php at root direct of magento system which include Mage.php at first code.
require_once "YOURMAGENTODIR/app/Mage.php";
umask(0);
Step2: set current store is admin and set Developer mode
Mage::app('admin');
Mage::setIsDeveloperMode(true);
Step3: Get Product Collection and create a loop for get one product by one by one
$productCollection=Mage::getResourceModel('catalog/product_collection');
Step4: fetch product image by one and remove image one using below code:
$remove=Mage::getModel('catalog/product_attribute_media_api')->remove($product->getId(),$eachImge['file']);
FULL CODE:
<?php
require_once "YOURMAGENTODIR/app/Mage.php";
umask(0);
Mage::app('admin');
Mage::setIsDeveloperMode(true);
$productCollection=Mage::getResourceModel('catalog/product_collection');
foreach($productCollection as $product){
echo $product->getId();
echo "<br/>";
$MediaDir=Mage::getConfig()->getOptions()->getMediaDir();
echo $MediaCatalogDir=$MediaDir .DS . 'catalog' . DS . 'product';
echo "<br/>";
$MediaGallery=Mage::getModel('catalog/product_attribute_media_api')->items($product->getId());
echo "<pre>";
print_r($MediaGallery);
echo "</pre>";
foreach($MediaGallery as $eachImge){
$MediaDir=Mage::getConfig()->getOptions()->getMediaDir();
$MediaCatalogDir=$MediaDir .DS . 'catalog' . DS . 'product';
$DirImagePath=str_replace("/",DS,$eachImge['file']);
$DirImagePath=$DirImagePath;
// remove file from Dir
$io = new Varien_Io_File();
$io->rm($MediaCatalogDir.$DirImagePath);
$remove=Mage::getModel('catalog/product_attribute_media_api')->remove($product->getId(),$eachImge['file']);
}
}
If you want to remove more products like 1000 or 5000 then use bottom one with direct query.
Before try this one take backup of your database
<?php
require_once 'app/Mage.php';
umask(0);
Mage::app();
set_time_limit(0);
ini_set('display_error','1');
$resource = Mage::getSingleton('core/resource');
$connection = $resource->getConnection('core_write');
$id = 101;
$product = Mage::getModel('catalog/product')->load($id);
$q = "DELETE FROM `catalog_product_entity_media_gallery` where entity_id = '".$product->getId()."'";
$connection->query($q);
?>
Accessing the Database for such things is a bad idea.
You can delete images ( or reorder them by changing the 'position' value ) using the following snippet in a custom module ( for the sake of simplicity i'm using ObjectManager, but you should place ProductFactory and ProductRepositoryInterface in the constructor )
$objectManager = ObjectManager::getInstance();
//Get ProductFactory in order to instatiate the Product Object
$productFactory = $objectManager->get('\Magento\Catalog\Model\ProductFactory');
//We have to use ProductRepositoryInterface in order to save the changes bellow to the product
$productRepository = $objectManager->get('\Magento\Catalog\Api\ProductRepositoryInterface');
//Load a Product by ID in this case 1
$product = $productFactory->create()->load(1);
//Gets an array containing arrays representing each image in the gallery
$mediaGalleryEntries = $product->getMediaGalleryEntries();
//Here we delete every image, you can use conditions in foreach
foreach ($mediaGalleryEntries as $key => $imageEntry) {
unset($mediaGalleryEntries[$key]);
}
//Finally set the altered entries and save using productRepository
$product->setMediaGalleryEntries($mediaGalleryEntries);
$productRepository->save($product);
The code above tested in Magento 2.3 and it also removes images from the filesystem. You can use it to either delete or alter an entry ( change position, image roles etc )
To view each imageEntry you can access its data using $imageEntry->getData()
I had to do something similar not too long ago - needed to replace all product images during an import.
This link helped a lot: http://www.sharpdotinc.com/mdost/2010/03/02/magento-import-multiple-images-or-remove-images-durring-batch-import/
Hopefully it will give you a nudge in the right direction.
DELETE FROM catalog_product_entity_media_gallery WHERE value_id NOT IN (SELECT * FROM (SELECT MIN(value_id) FROM `catalog_product_entity_media_gallery` GROUP BY LEFT(value,17), entity_id having count(*) > 1) x)
why 17 ?
The expamle you have duplicate like this:
/0/0/000116810609_1.jpg
/0/0/000116810609_2.jpg
/0/0/000116810609_3.jpg
/0/0/000116810609_4.jpg
LEFT(value,17)
/0/0/000116810609
/0/0/000116810609
/0/0/000116810609
/0/0/000116810609
No they are duplicates ;)
Place the below script in magento root and execute
<?php
require_once("app/Mage.php");
umask(0);
Mage::app();
$ob = new Clean();
$ob->removemedia();
Class Clean {
function removemedia() {
$read = Mage::getSingleton('core/resource')->getConnection('core_read');
$select = $read->select()
->from('catalog_product_entity_media_gallery', '*')
->group(array('value_id'));
$flushImages = $read->fetchAll($select);
echo count($flushImages);
$array = array();
foreach ($flushImages as $item1) {
$array[] = $item1['value'];
}
$valores = $array;
$pepe = 'media' . DS . 'catalog' . DS . 'product';
$leer = $this->listDirectories($pepe);
foreach ($leer as $item) {
try {
$item = strtr($item, '\\', '/');
if (!in_array($item, $valores)) {
$valdir[]['filename'] = $item;
unlink('media/catalog/product' . $item);
}
} catch (Zend_Db_Exception $e) {
} catch (Exception $e) {
//Mage::log($e->getMessage());
}
}
}
function listDirectories($path) {
if (is_dir($path)) {
if ($dir = opendir($path)) {
while (($entry = readdir($dir)) !== false) {
if (preg_match('/^\./', $entry) != 1) {
if (is_dir($path . DS . $entry) && !in_array($entry, array('cache', 'watermark'))) {
$this->listDirectories($path . DS . $entry);
} elseif (!in_array($entry, array('cache', 'watermark')) && (strpos($entry, '.') != 0)) {
$this->result[] = substr($path . DS . $entry, 21);
}
}
}
closedir($dir);
}
}
return $this->result;
}
}

Resources