My question: how do you use Magmi for bulk image import into Magento?
I've installed it, also got the 'Image attributes processor' plugin. Now what? The documentation on sourceforge is thin and I can't seem to find much on google either. A 'how to' would be appreciated, or hey, even a link to a tutorial.
Thank you. Cheers!
For a conversion to Magento I started out using Magmi as well for importing product data and images. After half a day I stopped with the images side cause I could not get it to work properly.
Did some investigating and Googling and came accross a script to import the images. Don't know from where anymore, but props to the creator of the base!
Seeing your question and remembering my struggle I wanted to share it with you. Hope it helps you out as well ;)
The script uses a table in the Magento-db which holds the image paths and sku's. It pulls the images from the path imports them directly into the Magento db.
Be carefull and testdrive on a test environment before firing it on a live site. Test it thoroughly to make sure it does not mess up your magento database. You also might want to check the image_attribute_id's to be correct as these are different per Magento version I noticed.
Hope it helps:)
############################################################################
#
# Change these variables to suit your store!
#
$_mediaBase = realpath('../media/catalog/product').'/';
$_imagesSrc = realpath('../media/import/_osc_media').'/';
// Image attribute_id's: image=79, small_image=80, thumbnail=81, gallery=82
$imgAttrIds = array(79,80,81,88);
$imageGalId = array(82);
require_once '../app/Mage.php';
#
############################################################################
#
# Debug (true/false)
#
$debug = false;
#
############################################################################
umask(0);
error_reporting(E_ALL);
ini_set('display_errors', '1');
Mage::setIsDeveloperMode(true);
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
$conn = Mage::getSingleton('core/resource')->getConnection('core_read');
$connW = Mage::getSingleton('core/resource')->getConnection('core_write');
//$images = scandir($_imagesSrc);
/*
* Relocate the images into Magento friendly format
*/
$imgArr = array();
$imgSkuArr[] = array();
$imgSrcArr[] = array();
$sql = "SELECT sku, image_path
FROM aa_image_paths";
$images = $conn->fetchAll($sql);
/**
* $images =
* [8] => Array(
* [sku] => ST-P006
* [image_path] => 47/ST-P006/Carying bag Heli P005A.jpg
* )
*/
#debug
if($debug == true){
echo '<p>Images: <pre>';
print_r($images);
echo '</pre>';
}//end: debug
//iterator
$y = $z = 0;
foreach($images as $image)
{
$pathChunks = explode('/', $image['image_path']);
$imgFile = end($pathChunks);
$firstDir = strtolower($_mediaBase . substr($imgFile,0,1));
$secondDir = strtolower($firstDir.'/' . substr($imgFile,1,1));
$imageEntityDir = strtolower('/' . substr($imgFile,0,1) . '/' . substr($imgFile,1,1) . '/' . $imgFile);
#debug
if($debug == true){
echo '<p>imgFile: ' . $imgFile . '<br />imageEntityDir: ' . $imageEntityDir . '</p>';
}//end: debug
/**
* Get the product_entity details
*/
$sql = "SELECT *
FROM catalog_product_entity
WHERE sku = '" . $image['sku'] . "'";
$_products = $conn->fetchAll($sql);
#debug
if($debug == true){
echo '<p>SQL: ' . $sql . '<br />';
echo '_products:<br />';
echo '<pre>';
print_r($_products);
echo '</pre></p>';
echo (isset($_products)) ? '<h6>products isset() = true</h6>' : '<h6>products isset() = false</h6>';
echo (!empty($_products))? '<h6>products empty() = false</h6>' : '<h6>products empty() = true</h6>';
}//end:debug
if(!empty($_products))
{
if(file_exists($_imagesSrc . $image['image_path'])){
$path = strtolower($secondDir . '/' . $imgFile);
if(!file_exists($path)) {
echo "Making $secondDir and copying to $path";
/**
* If NOT debug than do copy and mkdir stuff!
*/
if($debug == false)
{
if (!file_exists($secondDir)){
mkdir($secondDir, 0777, true);
}
copy($_imagesSrc . $image['image_path'], $path);
}//end: debug FALSE
}//end:if(!file_exists($path)) {
#debug
if($debug == true){
echo '<p>_imagesSrc + image_path: ' . $_imagesSrc . $image['image_path'] . '<br />';
echo 'image[image_path]' . $image['image_path'] . '<br />';
echo 'path: ' . $path . '<br />';
echo 'image[sku]: ' . $image['sku'] . '<br />';
echo 'imgEntDir: ' . $imageEntityDir . '<br />';
echo '</p>';
}//end: debug
/**
* Create the array for the product with the data.
* #var $product
*/
$productData = array();
$productData['sku'] = $image['sku'];
$productData['entity_id'] = $_products[0]['entity_id'];
$productData['imgSrc'] = $imageEntityDir;
#debug
if($debug == true){
echo 'productData: ' . $productData . '<br />';
echo 'productData[sku]: ' . $productData['sku'] . '<br />';
echo 'productData[entity_id]: ' . $productData['entity_id'] . '<br />';
echo 'productData[imgSrc]: ' . $productData['imgSrc'] . '<br />';
echo 'productData: <pre>';
var_dump($productData);
echo '</pre></p>';
}//end:debug
/**
* Check the existing images
*/
// General Base, small and thumb images
$sql = "SELECT *
FROM catalog_product_entity_varchar
WHERE entity_id = '" . $productData['entity_id'] . "'
AND attribute_id IN (".implode(",",$imgAttrIds).")";
$_imageAssoc = $conn->fetchAll($sql);
$existingImgs = array();
foreach($_imageAssoc as $img)
{
$existingImgs[$img['entity_id']][$img['attribute_id']] = $img;
}
// Gallery Images
$sql = "SELECT *
FROM catalog_product_entity_media_gallery
WHERE entity_id = '" . $productData['entity_id'] . "'";
$_galleryImgs = $conn->fetchAll($sql);
$existingGall = array();
foreach($_galleryImgs as $img)
{
$existingGall[$img['entity_id']][$img['attribute_id']] = $img;
#debug
if($debug == true){
echo '<p>img print_r: <br /><pre>';
print_r($img);
echo '</pre></p>';
}//end:debug
}
#debug
if($debug == true){
# print existingImg
echo '<p>existingImgs print_r: <br /><pre>';
print_r($existingImgs);
echo '</pre></p>';
# print existingGal
echo '<p>existingImgs print_r: <br /><pre>';
print_r($existingImgs);
echo '</pre></p>';
}//end:debug
/**
* Then associate to the product itself.
*/
//$insertData = array();
//$skusToInsert = array();
foreach($_products as $productArrId=>$product) {
$missingImgs = $imgAttrIds;
//$imageName = strtolower('/'.$product['sku'][0].'/'.$product['sku'][1].'/'.$product['sku'].'.jpg');
$imageName = $productData['imgSrc'];
#debug
if($debug == true){
echo '<p>Imagename print_r: <br /><pre>';
print_r($imageName);
echo '</pre></p>';
}//end:debug
// Check if it has an image associated already ...
if ( array_key_exists( $productData['entity_id'], $existingImgs) ) {
// Check which images exists and remove those already set
foreach ($imgAttrIds as $id=>$val) {
if ( array_key_exists( $val , $existingImgs[$productData['entity_id']] ) ) {
//if ( $existingImgs[$productData['entity_id']][$val]['value'] == "no_selection" ) {
$sql = "DELETE FROM catalog_product_entity_varchar WHERE value_id = '".$existingImgs[$productData['entity_id']][$val]['value_id']."'";
#debug
if($debug == true)
{
echo 'SQL base images: <pre>' . $sql . '</pre>';
}
else
{
//Execute the Query
$connW->query($sql);
}
//} else {
unset($missingImgs[$id]);
//}
}//end:f ( array_key_exists( $val
}//end: foreach ($imgAttrIds as $id=>$val) {
}//end;if ( array_key_exists( $productData['entity_id'], $existingImgs) ) {
// Check if it has Gallery images associated already ...
if ( array_key_exists( $productData['entity_id'], $existingGall) ) {
// Check which images exists and remove those already set
foreach ($imageGalId as $id=>$val) {
if ( array_key_exists( $val , $existingGall[$productData['entity_id']] ) ) {
//if ( $existingImgs[$productData['entity_id']][$val]['value'] == "no_selection" ) {
$sql = "DELETE FROM catalog_product_entity_media_gallery_value WHERE value_id = '".$existingGall[$productData['entity_id']][$val]['value_id']."'";
#debug
if($debug == true)
{
echo 'SQL gallery Value: <pre>' . $sql . '</pre>';
}
else
{
//Execute the Query
$connW->query($sql);
}
$sql = "DELETE FROM catalog_product_entity_media_gallery WHERE value_id = '".$existingGall[$productData['entity_id']][$val]['value_id']."'";
#debug
if($debug == true)
{
echo 'SQL gallery: <pre>' . $sql . '</pre>';
}
else
{
//Execute the Query
$connW->query($sql);
}
//} else {
unset($missingImgs[$id]);
//}
}//end:f ( array_key_exists( $val
}//end: foreach ($imgAttrIds as $id=>$val) {
}//end;if ( array_key_exists( $productData['entity_id'], $existingImgs) ) {
foreach ($imgAttrIds as $id=>$val) {
//Update the Media gallery items in DB
$sql = "INSERT INTO catalog_product_entity_varchar (entity_type_id, attribute_id, store_id, entity_id, value) VALUES " .
"(4, " . $val . ", 0, " . $productData['entity_id'] . ", '" . $imageName . "')";
#debug
if($debug == true)
{
echo 'SQL Insert1: <pre>' . $sql . '</pre>';
}
else
{
//Execute the Query
$connW->query($sql);
}
$y++;
}//end:foreach ($imgAttrIds as $id=>$val) {
foreach ($imageGalId as $id=>$val) {
//Update the
$sql = "INSERT INTO catalog_product_entity_media_gallery (attribute_id, entity_id, value) VALUES " .
"(".$val.", ".$productData['entity_id'].", '".$imageName."')";
//implode(",",$skusToInsert) . ";";
#debug
if($debug == true)
{
echo 'SQL Insert1: <pre>' . $sql . '</pre>';
}
else
{
//Execute the Query
$connW->query($sql);
}
//Update the Gallery value
/*
$sql = "INSERT INTO catalog_product_entity_media_gallery_value (value_id, store_id, position, disabled) VALUES " .
"((SELECT value_id FROM catalog_product_entity_media_gallery
WHERE attribute_id = '".$imageGalId."'
AND entity_id = '".$productData['entity_id']."'
AND value = '".$imageName."'),0, 1, 0)";
*/
$sql = "INSERT INTO catalog_product_entity_media_gallery_value (value_id, store_id, position, disabled) " .
"SELECT value_id, 0 store_id, 1 position, 0 disabled
FROM catalog_product_entity_media_gallery
WHERE attribute_id = '".$val."'
AND entity_id = '".$productData['entity_id']."'
AND value = '".$imageName."'";
#debug
if($debug == true)
{
echo 'SQL Insert1: <pre>' . $sql . '</pre>';
}
else
{
//Execute the Query
$connW->query($sql);
}
$z++;
}//end:foreach ($imgAttrIds as $id=>$val) {
}//end:foreach($_products as $productArrId=>$product) {
}//end: if(file_exists($_imagesSrc . $image['image_path']))
}//end: if(!empty($_products))
#debug
if($debug == true){
echo '<hr>';
}//end:debug
}//end:foreach($images as $image)
echo "<h5>Updated ". $y ." images for products. </h5>";
echo "<h5>Updated ". $z ." images in MediaGallery</h5>";
I had the same issue. Its pretty brittle. I realized it had created a new ./magento folder, and dumped the images in there. I merged that into my real magento folder & ran a reindex to fix it.
I then saw the 'path to Magento' setting was ../../magento/, changed this to ../../../magento/.
My setup is like this:
./magento/...files..
./magmi/...files...
It had dumped the images in a folder in ./magmi/magento/media/ because I was missing a ../ when telling magmi the path to my Magento folder. That didn't work because now it says it couldn't find the source images in ./media/import. The only viable solution was to manually merge the magento folders in to each other after each import. What a mess.
FYI In my spreadsheet I put in the image column /image.jpg just like that with the preceding slash.
Related
how can i generate a sitemap for processwire 3 for huebert-webentwicklung.de/sitemap.xml it doesen't work with the Plugin MarkupSitemapXML. Any idea how to get it work?
Thanks.
Create a new page template (sitemap.xml) then set the page output to be XML the the PW backend. Create a page and link it (set it to hidden).
function renderSitemapPage(Page $page) {
return
"\n<url>" .
"\n\t<loc>" . $page->httpUrl . "</loc>" .
"\n\t<lastmod>" . date("Y-m-d", $page->modified) . "</lastmod>" .
"\n</url>";
}
function renderSitemapChildren(Page $page) {
$out = '';
$newParents = new PageArray();
$children = $page->children;
foreach($children as $child) {
$out .= renderSitemapPage($child);
if($child->numChildren) $newParents->add($child);
else wire('pages')->uncache($child);
}
foreach($newParents as $newParent) {
$out .= renderSitemapChildren($newParent);
wire('pages')->uncache($newParent);
}
return $out;
}
function renderSitemapXML(array $paths = array()) {
$out = '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
array_unshift($paths, '/'); // prepend homepage
foreach($paths as $path) {
$page = wire('pages')->get($path);
if(!$page->id) continue;
$out .= renderSitemapPage($page);
if($page->numChildren) $out .= renderSitemapChildren($page);
}
$out .= "\n</urlset>";
return $out;
}
header("Content-Type: text/xml");
echo renderSitemapXML();
I want to disable the anchor tag of two subcategories. I used a free extension for topmenu. The code for subcategory menu is:
public function drawMenuItem($children, $level = 1)
{
$html = '<div class="itemMenu level' . $level . '">';
$keyCurrent = $this->getCurrentCategory()->getId();
foreach ($children as $child) {
if (is_object($child) && $child->getIsActive()) {
// --- class for active category ---
$active = '';
if ($this->isCategoryActive($child)) {
$active = ' actParent';
if ($child->getId() == $keyCurrent) $active = ' act';
}
// --- format category name ---
$name = $this->escapeHtml($child->getName());
if (Mage::getStoreConfig('custom_menu/general/non_breaking_space')) $name = str_replace(' ', ' ', $name);
$html.= '<a class="itemMenuName level' . $level . $active . '" href="' . $this->getCategoryUrl($child) . '"><span>' . $name . '</span></a>';
$activeChildren = $this->_getActiveChildren($child, $level);
if (count($activeChildren) > 0) {
$html.= '<div class="itemSubMenu level' . $level . '">';
$html.= $this->drawMenuItem($activeChildren, $level + 1);
$html.= '</div>';
}
}
}
$html.= '</div>';
return $html;
}
I tried to disable the two subcategories. But it didn't work. How can I give proper condition to disable particular two subcategories link?
I found a working code that exports the attributes to the browser interface,
like this:
this is the code:'
<?php
chdir(dirname(__FILE__));
require_once 'app/Mage.php';
Mage::app();
umask(0);
$productModel = Mage::getModel('Mage_Catalog_Model_Product');
$categoryModel = Mage::getModel('Mage_Catalog_Model_Category');
$resource = Mage::getModel('core/resource');
$db = $resource->getConnection('core_write');
$attributes = Mage::getSingleton('eav/config')
->getEntityType(Mage_Catalog_Model_Product::ENTITY)->getAttributeCollection();
foreach($attributes as $attribute) {
#if(!$attribute->getIsUserDefined()) continue;
if($attribute->getEntityTypeId() != 4) continue;
if($attribute->getFrontendInput() != 'select' && $attribute->getFrontendInput() != 'multiselect') continue;
echo $attribute->getFrontendLabel(). ' (' . $attribute->getAttributeCode() . ')' . "\n";
foreach ($attribute->getSource()->getAllOptions(false) as $option) {
if(empty($option['label'])) continue;
echo "," . $option['label']."\n";
}
echo "================,=================\n";
}
I would like to export this data to a csv, but I dont know how.
As another question I would also like to export the attribute sets and not only the attributes, is this possible?
Thanks in advance!
How can I find the tracking number associated with each order? I have created a script to output the data. I have tried so many variations, yet they all return blank/null.
Currently, it outputs
103236290 United States Postal Service - First-Class Mail Parcel Mar 23, 2013 10:12:59 PM
Note that the output is tab delimited, so there are two tabs between order id and shipment method.
<?php
//External script - Load magento framework
require_once($_SERVER['DOCUMENT_ROOT'] . "/store/app/Mage.php");
Mage::app('default');
$myOrder=Mage::getModel('sales/order');
$ship = Mage::getModel('sales/order_shipment');
$orders=Mage::getModel('sales/mysql4_order_collection');
$trackings=Mage::getResourceModel('sales/order_shipment_track_collection')->addAttributeToSelect('*')->addAttributeToFilter('parent_id',$ship->getId());
$trackings->getSelect()->order('entity_id desc')->limit(1);
$trackData = $trackings->getData();
$trackID = $trackData[0]['entity_id'];
$from = "2013-03-24 00:00:00"; // orders from date
$to= "2013-06-20 00:00:00"; // orders to date
//Optional filters you might want to use - more available operations in method _getConditionSql in Varien_Data_Collection_Db.
$orders->addFieldToFilter('total_paid',Array('gt'=>0)); //Amount paid larger than 0
$orders->addFieldToFilter('status',Array('eq'=>"Complete")); //Status is: "complete", "processing" "canceled" etc.
$orders->addAttributeToFilter('created_at', array(
'from' => $from,
'to' => $to,
));
$allIds=$orders->getAllIds();
foreach($allIds as $thisId) {
$myOrder->reset()->load($thisId);
echo "<pre>";
//print_r($myOrder);
//Fields to print
echo $myOrder->getRealOrderId() . " ";
echo $trackID . " ";
echo $myOrder->getShippingDescription() . " ";
echo $myOrder->getCreatedAtDate() . " ";
echo "\r\n";
echo "</pre>";
}
?>
Here is the working script. We figured it out :-)
<?php
//External script - Load magento framework
require_once($_SERVER['DOCUMENT_ROOT'] . "/store/app/Mage.php");
Mage::app('default');
$myOrder=Mage::getModel('sales/order');
$ship = Mage::getModel('sales/order_shipment');
$orders=Mage::getModel('sales/mysql4_order_collection');
$trackings=Mage::getResourceModel('sales/order_shipment_track_collection')->addAttributeToSelect('*')->addAttributeToFilter('parent_id',$ship->getId());
$trackings->getSelect()->order('entity_id desc')->limit(1);
$carrierInstances = Mage::getSingleton('shipping/config')->getAllCarriers();
$carriers['custom'] = Mage::helper('sales')->__('Custom Value');
foreach ($carrierInstances as $code => $carrier) {
if ($carrier->isTrackingAvailable()) {
$carriers[$code] = $carrier->getConfigData('title');
}
}
$from = "2013-03-24 00:00:00"; // orders from date
$to= "2013-06-21 00:00:00"; // orders to date
//Optional filters you might want to use - more available operations in method _getConditionSql in Varien_Data_Collection_Db.
$orders->addFieldToFilter('total_paid',Array('gt'=>0)); //Amount paid larger than 0
$orders->addFieldToFilter('status',Array('eq'=>"Complete")); //Status is: "complete", "processing" "canceled" etc.
$orders->addAttributeToFilter('created_at', array(
'from' => $from,
'to' => $to,
));
$allIds=$orders->getAllIds();
foreach($allIds as $thisId) {
$myOrder->reset()->load($thisId);
echo "<pre>";
//print_r($myOrder);
//Some random fields
echo $myOrder->getRealOrderId() . " ";
$trackings = Mage::getResourceModel('sales/order_shipment_track_collection')
->setOrderFilter($myOrder)
->getData();
foreach ($trackings as $tracking) {
echo $tracking['track_number'] . " ";
}
echo $carriers[$tracking['carrier_code']] . " ";
echo $myOrder->getCreatedAtDate() . " ";
// echo "'" . $myOrder->getStatus() . "',";
// echo "'" . $myOrder->getBillingAddress()->getLastname() . "',";
// echo "'" . $myOrder->getTotal_paid() . "',";
// echo "'" . $myOrder->getShippingAddress()->getTelephone() . "',";
// echo "'" . $myOrder->getPayment()->getCc_type() . "',"; // bad code
echo "\r\n";
echo "</pre>";
}
?>
I have been using K2 Scroller module developed by Land of Coder. When I use this module to display same category items in the items view the module displays items in the ascending order of the date created and it is the default and only setting available in the module parameter settings in the back-end. However, I want the module to display the items in date wise descending order. So I chose to edit the default code in the helper which I suppose is used to process items based on the back-end settings. And this is the part of the code in the helper file which I think controls the order:
public function __getList( $params ){
global $mainframe;
/*some irrelevant code removed*/
$condition = $this->buildConditionQuery( $params );
$limitDescriptionBy = $params->get('limit_description_by','char');
$ordering = $params->get( 'k2_ordering', 'created_desc');
$limit = $params->get( 'limit_items', 5 );
$ordering = str_replace( '_', ' ', $ordering );
$my = &JFactory::getUser();
$aid = $my->get( 'aid', 0 );
/*some irrelevant code removed*/
$extraURL = $params->get('open_target')!='modalbox'?'':'&tmpl=component';
$excludeIds = $params->get('exclude_ids', '');
$db = &JFactory::getDBO();
$date =& JFactory::getDate();
$now = $date->toMySQL();
$dateFormat = $params->get('date_format', 'DATE_FORMAT_LC3');
$limitDescriptionBy = $params->get('limit_description_by','char');
$isAuthor= $params->get('itemAuthor',0);
require_once ( JPath::clean(JPATH_SITE.'/components/com_k2/helpers/route.php') );
$query = "SELECT a.*, cr.rating_sum/cr.rating_count as rating, c.name as categoryname,
c.id as categoryid, c.alias as categoryalias, c.params as categoryparams, cc.commentcount as commentcount".
" FROM #__k2_items as a".
" LEFT JOIN #__k2_categories c ON c.id = a.catid" .
" LEFT JOIN #__k2_rating as cr ON a.id = cr.itemid".
" LEFT JOIN (select cm.itemid as id, count(cm.id) as commentcount from #__k2_comments as cm
where cm.published=1 group by cm.itemid) as cc on a.id = cc.id";
$query .= " WHERE a.published = 1"
. " AND a.access get('featured_items_show','0') == 0 ){
$query.= " AND a.featured != 1";
} elseif( $params->get('featured_items_show','0') == 2 ) {
$query.= " AND a.featured = 1";
}
if( trim($excludeIds) ){
$query .= " AND a.id NOT IN(".$excludeIds.") ";
}
$query .= $condition . ' ORDER BY ' . $ordering;
$query .= $limit ? ' LIMIT ' . $limit : '';
$db->setQuery($query);
$data = $db->loadObjectlist();
/*some irrelevant code removed*/
return $data;
}
/**
* build condition query base parameter
*
* #param JParameter $params;
* #return string.
*/
public function buildConditionQuery( $params ){
$source = trim($params->get( 'k2_source', 'k2_category' ) );
if( $source == 'k2_category' ){
$catids = $params->get( 'k2_category','');
if( !$catids ){
return '';
}
$catids = !is_array($catids) ? $catids : '"'.implode('","',$catids).'"';
$condition = ' AND a.catid IN( '.$catids.' )';
} else {
$ids = preg_split('/,/',$params->get( 'k2_items_ids',''));
$tmp = array();
foreach( $ids as $id ){
$tmp[] = (int) trim($id);
}
$condition = " AND a.id IN('". implode( "','", $tmp ) ."')";
}
return $condition;
}
Am I editing the right part of the code or am I missing something else.
I am looking forward to your help
Thanks.
Maybe the best way would be to modify the xml file of the module.
I looked at the code of Lof K2Scroller (v 2.2 for Joomla 2.5) and the different ordering options are there.
However if you want to modify the default option, you are in the right file, just replace 'created_desc' for 'created_asc' .