We did a migration from Zen Cart to Magento and we had to import all products with additional images. Almost every product had multiple images which was a problem because Magento doesn’t have built-in ability to upload multiple images for products. Why, i don’t know but we can easily extend Magento and create this ability.
The best way to accomplish this is to create a new module that will override the basic import module and perform the additional tasks we need. We also do it this way so that we do not touch the core code.
A few notes:
- This will NOT work on version 1.7.x. It was written for 1.4 and I have yet to write an updated version. Sorry.
- All pictures must be uploaded into the folder: “/media/import” else they will not be imported
- The import module uses the “sku” to identify each product, if you have already imported the products but now just want to add the extra images you only need the “sku” and “gallery” columns, you do not have to re-import all your products.
1. Create Directories
First of all, you need to create some directory structure that will hold your module files. Go to /app/code/local and create a directory representing your’s or your company’s name. All your modules will go into that directory. I will use this for the example:
/app/code/local/CDL.
Now we need to create the module directory. The module directory represents the name your module gets. I will use:
/app/code/local/CDL/Import in this example.
Every module needs a configuration file. This file is located under the etc/ subdirectory, so you need to create that directory as well. In my example it is:
/app/code/local/CDL/Import/etc.
2. Config File
Save this in the file: /app/code/local/CDL/Import/etc/config.xml
[sourcecode language=”xml”]
<?xml version="1.0"?>
<config>
<modules>
<CDL_Import>
<version>0.1.0</version>
</CDL_Import>
</modules>
<global>
<models>
<catalog>
<rewrite>
<convert_adapter_product>CDL_Import_Model_Gallery</convert_adapter_product>
</rewrite>
</catalog>
</models>
</global>
</config>
[/sourcecode]
3. Create the Model File
We create model in /App/code/local/CDL/Import/Model/Gallery.php
[sourcecode language=”php”]
<?php
/**
* Import Multiple Images during Product Import
*
*/
class CDL_Import_Model_Gallery extends Mage_Catalog_Model_Convert_Adapter_Product
{
/**
* Save product (import)
*
* @param array $importData
* @throws Mage_Core_Exception
* @return bool
*/
protected $custom_options = array();
public function saveRow(array $importData)
{
$product = $this->getProductModel()
->reset();
if (empty($importData[‘store’])) {
if (!is_null($this->getBatchParams(‘store’))) {
$store = $this->getStoreById($this->getBatchParams(‘store’));
} else {
$message = Mage::helper(‘catalog’)->__(‘Skip import row, required field "%s" not defined’, ‘store’);
Mage::throwException($message);
}
}
else {
$store = $this->getStoreByCode($importData[‘store’]);
}
if ($store === false) {
$message = Mage::helper(‘catalog’)->__(‘Skip import row, store "%s" field not exists’, $importData[‘store’]);
Mage::throwException($message);
}
if (empty($importData[‘sku’])) {
$message = Mage::helper(‘catalog’)->__(‘Skip import row, required field "%s" not defined’, ‘sku’);
Mage::throwException($message);
}
$product->setStoreId($store->getId());
$productId = $product->getIdBySku($importData[‘sku’]);
if ($productId) {
$product->load($productId);
}
else {
$productTypes = $this->getProductTypes();
$productAttributeSets = $this->getProductAttributeSets();
/**
* Check product define type
*/
if (empty($importData[‘type’]) || !isset($productTypes[strtolower($importData[‘type’])])) {
$value = isset($importData[‘type’]) ? $importData[‘type’] : ”;
$message = Mage::helper(‘catalog’)->__(‘Skip import row, is not valid value "%s" for field "%s"’, $value, ‘type’);
Mage::throwException($message);
}
$product->setTypeId($productTypes[strtolower($importData[‘type’])]);
/**
* Check product define attribute set
*/
if (empty($importData[‘attribute_set’]) || !isset($productAttributeSets[$importData[‘attribute_set’]])) {
/*$value = isset($importData[‘attribute_set’]) ? $importData[‘attribute_set’] : ”;
$message = Mage::helper(‘catalog’)->__(‘Skip import row, is not valid value "%s" for field "%s"’, $value, ‘attribute_set’);
Mage::throwException($message);*/
}
$product->setAttributeSetId($productAttributeSets[$importData[‘attribute_set’]]);
foreach ($this->_requiredFields as $field) {
$attribute = $this->getAttribute($field);
if (!isset($importData[$field]) && $attribute && $attribute->getIsRequired()) {
$message = Mage::helper(‘catalog’)->__(‘Skip import row, required field "%s" for new products not defined’, $field);
Mage::throwException($message);
}
}
}
$this->setProductTypeInstance($product);
if (isset($importData[‘category_ids’])) {
$product->setCategoryIds($importData[‘category_ids’]);
}
/* if category name is in csv file */
if (isset($importData[‘categories’])) {
$categoryIds = $this->_addCategories($importData[‘categories’], $store);
if ($categoryIds) {
$product->setCategoryIds($categoryIds);
}
}
foreach ($this->_ignoreFields as $field) {
if (isset($importData[$field])) {
unset($importData[$field]);
}
}
if ($store->getId() != 0) {
$websiteIds = $product->getWebsiteIds();
if (!is_array($websiteIds)) {
$websiteIds = array();
}
if (!in_array($store->getWebsiteId(), $websiteIds)) {
$websiteIds[] = $store->getWebsiteId();
}
$product->setWebsiteIds($websiteIds);
}
if (isset($importData[‘websites’])) {
$websiteIds = $product->getWebsiteIds();
if (!is_array($websiteIds)) {
$websiteIds = array();
}
$websiteCodes = explode(‘,’, $importData[‘websites’]);
foreach ($websiteCodes as $websiteCode) {
try {
$website = Mage::app()->getWebsite(trim($websiteCode));
if (!in_array($website->getId(), $websiteIds)) {
$websiteIds[] = $website->getId();
}
}
catch (Exception $e) {}
}
$product->setWebsiteIds($websiteIds);
unset($websiteIds);
}
foreach ($importData as $field => $value) {
if (in_array($field, $this->_inventoryFields)) {
continue;
}
if (in_array($field, $this->_imageFields)) {
continue;
}
$attribute = $this->getAttribute($field);
if (!$attribute) {
if(strpos($field,’:’)!==FALSE && strlen($value)) {
$values=explode(‘|’,$value);
if(count($values)>0) {
@list($title,$type,$is_required,$sort_order) = explode(‘:’,$field);
$title = ucfirst(str_replace(‘_’,’ ‘,$title));
$custom_options[] = array(
‘is_delete’=>0,
‘title’=>$title,
‘previous_group’=>”,
‘previous_type’=>”,
‘type’=>$type,
‘is_require’=>$is_required,
‘sort_order’=>$sort_order,
‘values’=>array()
);
foreach($values as $v) {
$parts = explode(‘:’,$v);
$title = $parts[0];
if(count($parts)>1) {
$price_type = $parts[1];
} else {
$price_type = ‘fixed’;
}
if(count($parts)>2) {
$price = $parts[2];
} else {
$price =0;
}
if(count($parts)>3) {
$sku = $parts[3];
} else {
$sku=”;
}
if(count($parts)>4) {
$sort_order = $parts[4];
} else {
$sort_order = 0;
}
switch($type) {
case ‘file’:
/* TODO */
break;
case ‘field’:
case ‘area’:
$custom_options[count($custom_options) – 1][‘max_characters’] = $sort_order;
/* NO BREAK */
case ‘date’:
case ‘date_time’:
case ‘time’:
$custom_options[count($custom_options) – 1][‘price_type’] = $price_type;
$custom_options[count($custom_options) – 1][‘price’] = $price;
$custom_options[count($custom_options) – 1][‘sku’] = $sku;
break;
case ‘drop_down’:
case ‘radio’:
case ‘checkbox’:
case ‘multiple’:
default:
$custom_options[count($custom_options) – 1][‘values’][]=array(
‘is_delete’=>0,
‘title’=>$title,
‘option_type_id’=>-1,
‘price_type’=>$price_type,
‘price’=>$price,
‘sku’=>$sku,
‘sort_order’=>$sort_order,
);
break;
}
}
}
}
continue;
}
$isArray = false;
$setValue = $value;
if ($attribute->getFrontendInput() == ‘multiselect’) {
$value = explode(self::MULTI_DELIMITER, $value);
$isArray = true;
$setValue = array();
}
if ($value && $attribute->getBackendType() == ‘decimal’) {
$setValue = $this->getNumber($value);
}
if ($attribute->usesSource()) {
$options = $attribute->getSource()->getAllOptions(false);
if ($isArray) {
foreach ($options as $item) {
if (in_array($item[‘label’], $value)) {
$setValue[] = $item[‘value’];
}
}
}
else {
$setValue = null;
foreach ($options as $item) {
if ($item[‘label’] == $value) {
$setValue = $item[‘value’];
}
}
}
}
$product->setData($field, $setValue);
}
if (!$product->getVisibility()) {
$product->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE);
}
$stockData = array();
$inventoryFields = isset($this->_inventoryFieldsProductTypes[$product->getTypeId()])
? $this->_inventoryFieldsProductTypes[$product->getTypeId()]
: array();
foreach ($inventoryFields as $field) {
if (isset($importData[$field])) {
if (in_array($field, $this->_toNumber)) {
$stockData[$field] = $this->getNumber($importData[$field]);
}
else {
$stockData[$field] = $importData[$field];
}
}
}
$product->setStockData($stockData);
$imageData = array();
foreach ($this->_imageFields as $field) {
if (!empty($importData[$field]) && $importData[$field] != ‘no_selection’) {
if (!isset($imageData[$importData[$field]])) {
$imageData[$importData[$field]] = array();
}
$imageData[$importData[$field]][] = $field;
}
}
foreach ($imageData as $file => $fields) {
try {
$product->addImageToMediaGallery(Mage::getBaseDir(‘media’) . DS . ‘import’ . $file, $fields, false, false);
}
catch (Exception $e) {}
}
/**
* Allows you to import multiple images for each product.
* Simply add a ‘gallery’ column to the import file, and separate
* each image with a semi-colon.
*/
try {
$galleryData = explode(‘;’,$importData["gallery"]);
foreach($galleryData as $gallery_img)
/**
* @param directory where import image resides
* @param leave ‘null’ so that it isn’t imported as thumbnail, base, or small
* @param false = the image is copied, not moved from the import directory to it’s new location
* @param false = not excluded from the front end gallery
*/
{
$product->addImageToMediaGallery(Mage::getBaseDir(‘media’) . DS . ‘import’ . $gallery_img, NULL, false, false);
}
}
catch (Exception $e) {}
/* End Modification */
$product->setIsMassupdate(true);
$product->setExcludeUrlRewrite(true);
$product->save();
/* Add the custom options specified in the CSV import file */
if(isset($custom_options)){
if(count($custom_options)) {
foreach($custom_options as $option) {
try {
$opt = Mage::getModel(‘catalog/product_option’);
$opt->setProduct($product);
$opt->addOption($option);
$opt->saveOptions();
}
catch (Exception $e) {}
}
}
}
return true;
}
protected $_categoryCache = array();
/* Add category and sub category. */
protected function _addCategories($categories, $store)
{
$rootId = $store->getRootCategoryId();
if (!$rootId) {
/* If stoder not create that mense admin then assign 1 to storeId */
$storeId = 1;
$rootId = Mage::app()->getStore($storeId)->getRootCategoryId();
}
if($categories=="")
return array();
$rootPath = ‘1/’.$rootId;
if (empty($this->_categoryCache[$store->getId()])) {
$collection = Mage::getModel(‘catalog/category’)->getCollection()
->setStore($store)
->addAttributeToSelect(‘name’);
$collection->getSelect()->where("path like ‘".$rootPath."/%’");
foreach ($collection as $cat) {
$pathArr = explode(‘/’, $cat->getPath());
$namePath = ”;
for ($i=2, $l=sizeof($pathArr); $i<$l; $i++) {
$name = $collection->getItemById($pathArr[$i])->getName();
$namePath .= (empty($namePath) ? ” : ‘/’).trim($name);
}
$cat->setNamePath($namePath);
}
$cache = array();
foreach ($collection as $cat) {
$cache[strtolower($cat->getNamePath())] = $cat;
$cat->unsNamePath();
}
$this->_categoryCache[$store->getId()] = $cache;
}
$cache =& $this->_categoryCache[$store->getId()];
$catIds = array();
foreach (explode(‘,’, $categories) as $categoryPathStr) {
$categoryPathStr = preg_replace(‘#\s*/\s*#’, ‘/’, trim($categoryPathStr));
if (!empty($cache[$categoryPathStr])) {
$catIds[] = $cache[$categoryPathStr]->getId();
continue;
}
$path = $rootPath;
$namePath = ”;
foreach (explode(‘/’, $categoryPathStr) as $catName) {
$namePath .= (empty($namePath) ? ” : ‘/’).strtolower($catName);
if (empty($cache[$namePath])) {
$cat = Mage::getModel(‘catalog/category’)
->setStoreId($store->getId())
->setPath($path)
->setName($catName)
->setIsActive(1)
->save();
$cache[$namePath] = $cat;
}
$catId = $cache[$namePath]->getId();
$path .= ‘/’.$catId;
}
if ($catId) {
$catIds[] = $catId;
}
}
return join(‘,’, $catIds);
}
}
[/sourcecode]
4. Load the Moduel
Save this in the file “/app/etc/modules/CDL_Import.xml”
[sourcecode language=”xml”]
<?xml version="1.0"?>
<config>
<modules>
<CDL_Import>
<active>true</active>
<codePool>local</codePool>
</CDL_Import>
</modules>
</config>
[/sourcecode]
5. Clear Cache and Check Results
Clear the cache!
We import products with csv file and example of csv:
[sourcecode language=”csv”]
"store","websites","attribute_set","type"……"gallery"
"admin","base","Default","simple"……"/tees/nautical_girls650.jpg;/tees/nautical_girls750.jpg"
[/sourcecode]
You can see, we added a column ”gallery”
and pictures are separated with “;”
All pictures must be uploaded in folder: “/media/import” and you can go to: (Admin > System > Import/Export > Profiles >> Import All Products) and import can begin…
I would just like to say thank you. This and the export extension saved me hours of work. It’s amazing that magento doesn’t have this built in already.
Can I say it works perfect, I have been trying for hours to make this happen!
Thanks Guys!
Hi, please tell me if this extension works on Magento 1.5.1.0. It doesn’t import the images on my version.
Thank you for this extension.
Hey Martin,
Did you make sure that you uploaded all your images into the folder “media/import” on the new Magento install?
CDL.
Hi
Thanks for your code
for me importing is working fine but the problem is its not updating back end & front end also.
Please help me
It’s not working in 1.7.0.2 version… media field is all ready there…
Any solutions?
This will not work on version 1.7.x. It was written for 1.4 and I have yet to write an updated version. Sorry.
it does import additional images in 1.9 version but not the main image, small and thumbnail… any solutions?
Hi there,I am also using this script but eoteuncnr a strange problem and looking for a sloution for 2 full days now.Magento 1.4.1Import works well, base, thumbnail and additional gallery images.Somehow the pictures are only shown on the product page (gallery) the base image thumbnail is not shown in the categorie listings.After checking in the admin panel (in the storeview I used during import) the the specific picture is there and base, small and thumbnail are selected for it.No matter what changes I make in the storeview, the thubnail image wont show up.After switching to Standard Storeview saving anything inside the image section and turning back to my specific storeview EVERYTHING works.Anyone got an Idea why all values on the specific storeview are correct in the admin panel but wont be used in frontend?