Magento 1.7 Append Complex Data - magento

I am trying to append a category id to a large number of SKUs in Magento 1.7. I have used the Import > Append Complex Data and, although it checked the file and ran ok, it did not add these SKUs to the category I wanted them in.
So, the objective is to leave all these SKUs in the categories there are in now but add an additional category.
Any help would be appreciated. Even if it is a different method entirely.

The fastest way to do this is to directly insert this as a SQL query using:
INSERT INTO `catalog_category_product` (
`category_id` ,
`product_id` ,
`position`
)
VALUES (
'4', '34', '0'
), (
'4', '35', '0'
);
In this case, it would add the category Id of 4 to the products with Id 34 and 35. You can create a small PHP script to dynamically create such a query from your file of SKUs and Category Ids.
Reindex after your query was successfully executed.
Alternatively, using the Magento eco-system and not the database, you can do this:
$categoryIds = array();
$toBeUpdatedProducts = array(4,6,7); // all the Ids you want to update
$newCategoryId = 65; // Id of new category
foreach ($toBeUpdatedProducts as $productId) {
$product = Mage::getModel('catalog/product')->load($productId);
$categoryIds = $product->getCategoryIds();
$categoryIds[] = $newCategoryId; // Add new category to existing ones
$product->setCategoryIds($categoryIds);
$product->save();
}

Related

Advice with Magento large productsfile csv import

I need to import 40.000 products.
These products together are generating 600.000 attribute values
There is a csv file with product info (Sku, Name, Description and Ean) and a seperate sheet with only the attributes(600K)
On each row i have:
Sku - Attribute - Value
e.g.
123 Color Green
123 Length 120
123 Size XL
456 Color White
456 Length 260
etc..
I have filtered all duplicates out which resulted in 2200 unique Attributes.
What should i Do with these attributes?
Put them all in one attributeset? Will it hurt the performance of the webshop?
And what about the attributesheet?
How should i convert the structure of the presented data so it will be usefull for for import in magent? Cause magento needs all attribute names as columnheaders?
I have tried to collect teh attribute values with VLOOKUP but run into memory problems on my MACbook Pro. Fill down one column with a formula doesn't work wit this amount of records.
Maybe there is a solution programmticly.
Thanks!
I would suggest to create product pragmatically.
Import product into a mysql table (tables) and create using magento code directly.
You can create configurable attributes and use its id when creating products.
You should think about using uRapidFlow.
While I am not a huge fan of the fact that it uses direct sql to import products, it has been around for some time and is known to be very reliable and very fast.
//add new products
$product = Mage::getModel('catalog/product');
$product->setSku($sku);
$product->setStatus(1);
$product->setName($name);
$product->setDescription($details);
$product->setShortDescription($description);
$product->setPrice(0);
$product->setTypeId('simple');
$product->setAttributeSetId(4); // enter the catalog attribute set id here
$product->setCategoryIds($categoryIds); // id of categories
$product->setWeight(1.0);
$product->setTaxClassId($taxClassId);
$product->setVisibility($visibility);
$product->setStatus($productStatus);
$product->setColor('color',$color_id); // u need to get attribute code for dropdown items
$product->setData('material', $avid);
$product->setBrand($brand);
/*$product->setStockData(
array(
'manage_stock' => 1,
'is_in_stock' => 1,
'qty' => $qty
)
);*/
// assign product to the default website
$product->setWebsiteIds(array(1,2,3,4));
try{
$product->save();
$i++;
;
}catch (Exception $e) {
echo Mage::logException($e->getMessage());
}
$id = Mage::getModel('catalog/product')->getIdBySku(trim($sku)); //get product id after create
//add dropdown items for attribute u created already, u need to make this as function to get option id before add a product
$attribute_model = Mage::getModel('eav/entity_attribute');
$attribute_options_model= Mage::getModel('eav/entity_attribute_source_table') ;
$attribute_code = $attribute_model->getIdByCode('catalog_product', $attribute_code);
$attribute = $attribute_model->load($attribute_code);
$attribute_table = $attribute_options_model->setAttribute($attribute);
$options = $attribute_options_model->getAllOptions(false);
foreach($options as $option)
{
if (strtolower($option['label']) == strtolower($label))
{
$optionId=$option['value'];
break;
}
}
//u need to run thru a loop to add products

magento getting product id based on custom option value

I need to retrieve an array of cross sell product ids from a product based on a product id retrieved based on a value in a product custom option.
I have researched how to get it using straight MySQL statements. How do I get it using the standard magento calls?
here is the MySQL process:
Select option_type_id from mage_catalog_product_option_type_title where option_type_id EQ 'desired value';
then:
Select option_id from mage_catalog_product_option_type_value where option_type_id EQ option_type_id; (from above step)
then:
Select product_id from mage_catalog_product_option where option_id EQ option id; (from previous step)
then:
Select linked_product_id from mage_catalog_product_link where product_id EQ product_id (from previous step) AND link_type_id ='5';
(I'm experienced in PHP/MySQL but barely past novice level in Magento)
Can anyone help? Thank you very, very much!
Mark
Try this solution:
$collection = Mage::getModel('catalog/product_link')->getCollection()->addFieldToFilter('option_type_id','desired value’);
$collection->join(array('option' => 'catalog/product_option'), 'main_table.product_id = option.product_id')
->join(array('option_value' => 'catalog/product_option_type_value'), 'option.option_id = option_value.option_id');
var_dump($collection->getFirstItem()->getData());
And this is how it generally works:
$collection = Mage::getModel('catalog/product_option_value')->getCollection()->addFieldToFilter('option_type_id','desired value’);
$collection = Mage::getModel('catalog/product_option')->getCollection()->addFieldToFilter('option_id',$collection->getFirstItem()->getOptionId());
$collection = Mage::getModel('catalog/product_link')->getCollection()->addFieldToFilter('product_id',$collection->getFirstItem()->getProductId());
var_dump($collection->getFirstItem()->getData());

Magento - get order id from increment id

How do you get the Order Id from magento Order Increment Id?
I can use the following get the product id from SKU:
$product_id = Mage::getModel('catalog/product')->getIdBySku('ABCD1234');
The above example lets me get just the database entity_id of a product without loading everything. I want to achieve the same for order.
In a Magento model, the load method can take an optional second argument of what attribute to load by.
So, in your case, the following should work:
$order = Mage::getModel('sales/order')->load($incrementId, 'increment_id');
$id = $order->getId();
In more complex cases, e.g. where you want to load by a combination of fields, you can load a collection, and get the first element of the collection. In your case, you'd do it like this:
$order = Mage::getModel('sales/order')->getCollection()
->addFieldToFilter('increment_id', $increment_id)
->getFirstItem();
You can load an order from the IncrementId.
$orderIncrementId = "1000001";
$order = Mage::getModel('sales/order')->loadByIncrementId($orderIncrementId);
echo $order->getId();
If you want to fetch only order_id then simply use mysql query, if you want order_id in for loop, it is not load entire order object and it is very quick and fast, you don't need to load order object model.
$write = Mage::getSingleton('core/resource')->getConnection('core_read');
$result=$write->query("SELECT entity_id FROM `sales_flat_order` WHERE `increment_id` = 'your increment id' ");
$row = $result->fetch();
echo $row['entity_id'];

Magento - cms/page collection - apply filter to return only pages which are unique to a given store id (ie not also assigned to other stores)

I can use:
Mage::getModel('cms/page')->getCollection()->addStoreFilter($store_id);
to retrieve a collection of CMS pages filtered by Store Id.
But how do I get it to remove ones which are also assigned to other stores?
ie: I do not want it to return items which have 'All Store Views' as the Store View. (Or any other additional store id assigned to that CMS page.) It has to only return pages unique to that one store.
I am extending the Aitoc permissions module, so that Store Admins cant view or edit CMS pages and static blocks which might impact other stores. This involves filtering those items from the grid.
There's no native collection method to do this, so you'll need to
Query the cms_page_store table for pages unique to a given store
Use the results from above in your filter
I didn't fully test the following, but it should work (and if it doesn't, it'll give you a good start on your own query)
$page = Mage::getModel('cms/page');
$resource = $page->getResource();
$read = $resource->getReadConnection();
#$select = $read->query('SELECT page_id FROM ' . $resource->getTable('cms/page_store') . ' GROUP BY store_id');
//set total count to look for. 1 means the page only appears once.
$total_stores_count_to_look_for = '1';
//get the table name. Need to pass through getTable to ensure any prefix used is added
$table_name = $resource->getTable('cms/page_store');
//aggregate count select from the cmd_page_store database
//greater than 0 ensures the "all stores" pages aren't selected
$select = $read->query('SELECT page_id as total
FROM '.$table_name.'
WHERE store_id > 0
GROUP BY page_id
HAVING count(page_id) = ?',array($total_stores_count_to_look_for));
//fetch all the rows, which will be page ids
$ids = $select->fetchAll();
//query for pages using IDs from above
$pages = Mage::getModel('cms/page')->getCollection()->addFieldToFilter('page_id',array('in'=>$ids));
foreach($pages as $page)
{
var_dump($page->getData());
}
If you have thousands and thousands of CMS pages it may be worth it to alter the cms/page collection's select to join in aggregate table data. I'll leave that as an exercise for the reader, as those sorts of joins can get tricky.
$collection = Mage::getModel('cms/page')->getCollection();
$collection->getSelect()
->join(
array('cps' => $collection->getTable('cms/page_store')),
'cps.page_id = main_table.page_id AND cps.store_id != 0',
array('store_id')
)
->columns(array('stores_count' => new Zend_Db_Expr('COUNT(cps.store_id)')))
->group('main_table.page_id')
->having('stores_count = ?', 1)
->having('cps.store_id = ?', $storeId)
;
Fusing some elements of the solutions proposed by Alan and Vitaly with my own cumbersome understanding, I achieved what I needed with the following code.
To put into context, I was extending the Aitoc permissions module, so that Store Admins cant view or edit CMS pages and static blocks which might impact other stores. This involved filtering those items from the grid.
$collection = Mage::getModel('cms/page')->getCollection();
$collection->addStoreFilter(Mage::helper('aitpermissions')->getStoreIds());
$conn = Mage::getSingleton('core/resource')->getConnection('core_read');
$page_ids = array();
foreach($collection as $key=>$item) {
$page_id = $item->getId();
$results = $conn->fetchAll("SELECT * FROM cms_page_store
WHERE page_id = ".$page_id.";");
$count = 0;
$arr_stores = array();
foreach($results as $row) {
$arr_stores[] = $row['store_id'];
$count++;
}
//We dont want to show the item if any of the following are true:
//The store id = 0 (Means its assigned to All Stores)
//There is more than one store assigned to this CMS page
if( in_array('0',$arr_stores) || $count>1) {
//This removes results from the grid (but oddly not the paging)
$collection->removeItemByKey($key);
}
else {
//build an array which we will use to remove results from the paging
$page_ids[] = $page_id;
}
}
//This removes results from paging (but not the grid)
$collection->addFieldToFilter('page_id',array('in'=>$page_ids));
I'm not sure why I needed to use two different methods to filter from the paging and the grid.
The site uses magento 1.5 so perhaps there is an issue related to that.
Either way, this solution worked for me.
My solution to add field store_id to pages collection via join, and use collection method addFieldToFilter().
$pages = Mage::getModel('cms/page')->getCollection();
$pages->getSelect()->joinInner(
array('cms_page_store' => 'cms_page_store'),
'main_table.page_id = cms_page_store.page_id',
array()
);
$pages->addFieldToFilter('store_id', ['in' => [1, 2]]);

Magento - addStoreFilter not working?

When getting a product collection in Magento, I would expect the StoreFilter to do just that, filter by the current store. But I can't get it to work.
Say I have 2 stores set up like so:
And both stores have a different root category. Main Store is the default sample data, Store2 has just one product I added. I would have thought that using the store filter, only products within the root category of the current store would show up. But I'm getting every product showing. I'm testing this by placing the following in my category view template:
$store_id = Mage::app()->getStore()->getId();
$_testproductCollection = Mage::getResourceModel('reports/product_collection')
->setStoreId($storeId)
->addStoreFilter($store_id)
->addAttributeToSelect('*');
$_testproductCollection->load();
foreach($_testproductCollection as $_testproduct){
echo $this->htmlEscape($_testproduct->getName());
};
If I echo the store ID, it's giving me the correct number. I have only one product in Store 2, so why am I getting every product from all stores returned? I can set every product in Main Store to not show in Store2 and then add a visibility filter, but that would take forever.
Also, I just noticed, if I echo the products store ID, I get the current ID, not the store it's assigned to:
echo $_testproduct->getStoreId()
What's going on?
UPDATE (April 8 2011):
OK, so I tried joining the fields so that the store_id is included (as suggested below), the section of code {{table}}.store_id = 1 is just setting all the products to have a store_id of 1. How can I just get the store_id associated with the product?
$_testproductCollection = Mage::getResourceModel('catalog/product_collection');
$_testproductCollection->joinField('store_id', 'catalog_category_product_index', 'store_id', 'product_id=entity_id', '{{table}}.store_id = 1', 'left');
$_testproductCollection->getSelect()->distinct(true);
$_testproductCollection->addAttributeToSelect('*')->load();
foreach($_testproductCollection as $_testproduct){
echo $this->htmlEscape($_testproduct->getName())."<br/>";
echo "STORE IS ".$_testproduct->getData('store_id')."<br/>";
};
If I check the catalog_category_product_index table of my db, the store_id's are correct.
$_testproductCollection should look like this $_testproductCollection = Mage::getResourceModel('reports/product_collection')->addAttributeToSelect('*')->addStoreFilter().
If You print SELECT from that collection You will see that there ain't any store column, so addStoreFilter() can't apply WHERE.
You should use joinField() on Your collection and add store_id column from catalog_product_entity_varchar table.
EDIT
Sorry to keep You waiting ;)
$collection = Mage::getResourceModel('catalog/product_collection');
$collection->joinField('store_id', 'catalog_category_product_index', 'store_id', 'product_id=entity_id', '{{table}}.store_id = 1', 'left');
$collection->getSelect()->distinct(true);
This should do the trick, but just to be sure, please check if you're getting right products :)
This worked for me:
Mage::app()->setCurrentStore($storeId);
$productCollection = Mage::getModel('catalog/product')
->getCollection()
->addStoreFilter()
->addAttributeToSelect(array('sku','price'));
OK, I think this works, haven't tested too much but seems to have done the trick. You need to first get your stores root category id, then join some fields so you have access to the products "category_id", then filter using that:
$_rootcatID = Mage::app()->getStore()->getRootCategoryId();
$_testproductCollection = Mage::getResourceModel('catalog/product_collection')
->joinField('category_id','catalog/category_product','category_id','product_id=entity_id',null,'left')
->addAttributeToFilter('category_id', array('in' => $_rootcatID))
->addAttributeToSelect('*');
$_testproductCollection->load();
foreach($_testproductCollection as $_testproduct){
echo $this->htmlEscape($_testproduct->getName())."<br/>";
};
I think
You don't need to do any joins as the magento's setStoreId() will work.
$collection = Mage::getModel("catalog/product")
->getCollection()
->setStoreId(1) //change store Id according your needs
->addAttributeToSelect(array('name','url','sku'))
->setPageSize(20);
This will get maximum 20 products from store id 1

Resources