Magento - Move a category programmatically - magento

How do I move a category to another category with all child categories?
I have tried the following solution:
$nodeId = 2269;
$parentId = 2268;
$tree = Mage::getResourceModel('catalog/category_tree')->load();
$node = $tree->getNodeById($nodeId);
$parentNode = $tree->getNodeById($parentId);
$parentChildren = explode(',', $parentNode->getChildren());
$afterId = array_pop($parentChildren);
$prevNode = $tree->getNodeById($afterId);
if (!$prevNode || !$prevNode->getId()) {
$prevNode = null;
}
$tree->move($node, $parentNode, $prevNode);
However my result is somewhat twisted. If I move to the root-category the move works, but if I move to a child-category I get faulty results and disappearing categories.
These are the values of the field path in the database:
Old: 1/2/3/2175/2269
New: 1/2/3/2175/2226/2268/2269
Correct: 1/2/3/2226/2268/2269

The solution was quite simple, this one doesn't mess up the paths. However it feels like this method is slower.
$categoryId = 2269;
$parentId = 2268;
$category = Mage::getModel('catalog/category')->load($categoryId);
$category->move($parentId, null);

$parent = Mage::getModel('catalog/category')->load('REPLACE_WITH_PARENT_ID');
$category = Mage::getModel('catalog/category');
$category->addData(array('name' => 'YOUR_CATEGORY_NAME', 'path' => $parent->getPath()));
$category->save();

Related

display parent category and sub category and sub sub category name from product collection

I am try to write product categories name into csv file. My requirement is have three column in csv "parent category name" and "subcategory name" "subsub category name"
So i get product collection and got a categories ids by below code.
$products = Mage::getModel("catalog/product")->getCollection();
foreach ($products as $product) {
$catIds = $product->getCategoryIds();
}
Example tree structure: CategoryName -- (Category Id)
Main Category --(3)
Sub_Cat_1 (4)
SubSub_Cat_1 (6)
SubSub_Cat_2 (7)
SubSub_Cat_3 (8)
Sub_Cat_2(5)
SubSub_Cat_4 (9)
SubSub_Cat_5 (10)
So i got the $catIds = array(3,4,5,6,7) but i want name with relation.
So i want below output in CSV file.
Parent_Cat | Sub_Cat | SubSub_Cat
Main Category | Sub_Cat_1,Sub_Cat_2 | SubSub_Cat_1,SubSub_Cat_2
I have tried lot of methods but no luck.
So please kindly help in advance to achieve.
Thanks,
You can have an array containing all the categories on their specific level (each key will represent a level) like this:
$categoriesLevels = array();
$categoryModel = Mage::getModel('catalog/category');
$tree = $categoryModel->getTreeModel();
$tree->load();
$catIds = $tree->getCollection()->getAllIds();
foreach ($catIds as $catId){
$category = Mage::getModel('catalog/category')->load($catId);
$catLevel = $category->getLevel();
if (!isset($categoriesLevels[$catLevel])) {
$categoriesLevels[$catLevel] = array();
}
$categoriesLevels[$catLevel] = array_merge($categoriesLevels[$catLevel],array($category->getName()));
}
$categoriesLevels = array_filter($categoriesLevels);
So $categoriesLevels[0] will contain the name of the Root Catalog, $categoriesLevels[1] will contain the name of the Default Category, $categoriesLevels[2] will contain the name of all the Subcategories, $categoriesLevels[3] will contain the name of all the SubSubcategories, etc.
edit
If you only want the categories for a specific product, just change the way the $catIds are obtained:
$categoriesLevels = array();
$catIds = $product->getCategoryIds();
foreach ($catIds as $catId){
$category = Mage::getModel('catalog/category')->load($catId);
$catLevel = $category->getLevel();
if (!isset($categoriesLevels[$catLevel])) {
$categoriesLevels[$catLevel] = array();
}
$categoriesLevels[$catLevel] = array_merge($categoriesLevels[$catLevel], array($category->getName()));
}
$categoriesLevels = array_filter($categoriesLevels);
Finally i find the solution so please check this for my answer.
$products = Mage::getModel("catalog/product")->getCollection();
$products->addAttributeToFilter('status', 1);
$products->addAttributeToSelect('*');
$cats = $product->getCategoryIds();
$cat_lel_one = array();
$cat_lel_two = array();
$cat_lel_third = array();
foreach ($cats as $category_id) {
$_cat = Mage::getModel('catalog/category')->setStoreId(Mage::app()->getStore()->getId())->load($category_id);
$cat_info = $_cat->getData();
if($cat_info['level'] == 1){
$cat_lel_one[] = $_cat->getName();
}
if($cat_info['level'] == 2){
$cat_lel_two[] = $_cat->getName();
}
if($cat_info['level'] == 3){
$cat_lel_third[] = $_cat->getName();
}
}
My first level of categories in $cat_lel_one variable. My Second level
of categories in $cat_lel_two variable. My third level of categories
in $cat_lel_third variable.

Find parent id of product in magento

here is my code.
$storeId = Mage::app()->getStore()->getId();
$session = Mage::getSingleton('checkout/session');
foreach($session->getQuote()->getAllItems() as $item)
{//how to find parent id here}
At the above mentioned comment I want to access parent id of that particular product.
Please Help ..
Try below code, may be it will help you
if($item->getTypeId() == "simple"){
$parentIds = Mage::getModel('catalog/product_type_grouped')->getParentIdsByChild($item->getId()); // check for grouped product
if(!$parentIds)
$parentIds = Mage::getModel('catalog/product_type_configurable')->getParentIdsByChild($item->getId()); //check for config product
}
You can use this to get the parent
foreach(...) {
$parents = $item->getTypeInstance()->getParentIdsByChild($item->getId());
//if you need to load the parent
if(!empty($parents)) {
$parentProd = Mage::getModel('catalog/product')->load($parents[0]);
//do something
}
}
this might help you:
$product = Mage::getModel('catalog/product');
$product->load($productId);
$grouped_product_model = Mage::getModel('catalog/product_type_grouped');
$groupedParentId = $grouped_product_model->getParentIdsByChild($product->getId());

Get custom Attribute

I'm wonder how can I get custom attribute,
My custom attribute call "tim_color"
I was try get by $_product->getAttributeText('tim_color');
after execute I get fatal error Call to a member function getAttributeText() on a non-object
when I'm used
$data['color'] = $product->getTim_color();
in the result i'm get id, but I need the name of atrribute, how can I resolve this problem
My code of script:
$mage_csv = new Varien_File_Csv(); //mage CSV
$products_model = Mage::getModel('catalog/product')->getCollection();; //get products model
$products_model ->addAttributeToSelect('*');
$products_row = array();
foreach ($products_model as $prod)
{
#print_r($prod);
$product = Mage::getModel('catalog/product')->load($prod->getId());
$data = array();
$data['id_product'] = $product->getId();
$data['color'] = $product->getTim_color();
$data['sku'] = $product->getSku();
$data['name'] = strip_tags($product->getName());
$data['description'] = trim(preg_replace('/\s+/', ' ', strip_tags($product->getDescription())));
$data['price'] = $product->getPrice();
$products_row[] = $data;
}
thx for help
Try,
$_product->getData(’tim_color’);
I hope you can get the attribute value by getAttributeText() also. Check out,
$_product = Mage::getModel('catalog/product')->load($item->getId()); //getting product
$_product->getAttributeText('tim_color'); //getting custom attribute value
Detailed discussions are here and here.

Creating Configurable product on import csv

When a new simple product is added (via CSV or manually) we need to check if the appropriate configurable product has been added (where SKU = "item_number-item_colour_code" e.g. BLEA2606B-BK001). If the configurable product exists then associate the simple product. If the configurable product does not exist then create using the data in the simple product AND then associate the simple product.
I found some help from HERE but don't know how check if configurable product already exists, and if not how to create one.
Here is the script file that I downloaded. Can anybody advice if this will work with my scenario?
EDITED
I have scraped the idea of creating configurable product in import. I am doing it by capturing the catalog_product_save_after event now. Hopefully that will get me somewhere.
EDITED 2
OK, Finally, I have it working. I'm doing it in the observer. I know it slows down the product save process but couldn't think of any other way. Thats what I'm doing:
public function productSave($observer)
{
$p = $observer->getProduct();
$pr = Mage::getModel('catalog/product')->load($p->getId());
$attributeValue = Mage::getResourceModel('catalog/product')->getAttributeRawValue($pr->getId(), 'size'); //loads attribute option value
$qtyStock = Mage::getModel('cataloginventory/stock_item')->loadByProduct($pr)->getQty();
Mage::log('Qty: '.$qtyStock.$pr->getId(), null, 'test.txt');
if ($pr->getTaxClassId() == '0' || !isset($pr->getTaxClassId)) {
$taxClass = 'None';
} elseif ($pr->getTaxClassId() == '2') {
$taxClass = 'Taxable Goods';
} elseif ($pr->getTaxClassId() == '4') {
$taxClass = 'Shipping (not used by AvaTax)';
} elseif ($pr->getTaxClassId() == '5') {
$taxClass = 'General';
}
$_configSku = $pr->getItemNumber().'-'.$pr->getItemColourCode();
$category = array();
$categoryCollection = $pr->getCategoryCollection();
foreach ($categoryCollection as $cat) {
$category[] = $cat->getId();
}
$_configExist = Mage::getModel('catalog/product')->loadByAttribute('sku',$_configSku);
if($_configExist && $_configSku != '-') {
//Mage::log($_configExist, null, 'test.txt');
//Mage::log($_configSku, null, 'test.txt');
$new_ids = array();
$current_ids = $_configExist->getTypeInstance()->getUsedProductIds();
foreach($current_ids as $temp_id)
{
$new_ids[] = $temp_id;
}
}
if(!$_configExist && $_configSku != '-') {
$att_size = Mage::getModel('eav/entity_attribute')->loadByCode('catalog_product','size');
$att_sizes = $this->__getAttList('size');
$confProduct = Mage::getModel('catalog/product');
$confProduct->setAttributeSetId('10');
$confProduct->setSku($_configSku);
$confProduct->setTypeId('configurable');
$confProduct->setName($pr->getName());
$confProduct->setDescription($pr->getDescription());
$confProduct->setShortDescription($pr->getShortDescription());
$confProduct->setCreatedAt(strtotime('now'));
$confProduct->setPrice($pr->getPrice());
$confProduct->setStatus(1);
$confProduct->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH);
$confProduct->setWebsiteIDs(array(1));
$confProduct->setStockData(array(
'is_in_stock' => 1,
'qty' => 9999
));
$confProduct->setTaxClassId( $taxClass );
$confProduct->setCategoryIds( $category );
/* Set Configurable Attributes */
$confProduct->setConfigurableAttributesData($tmp = array(
array_merge($att_size->getData(), array('label' => '', 'values' => $size_values))
));
$simpleProducts = array(
$pr->getId()=>array( 'attribute_id'=>'145', 'label'=>'size', 'value_index'=>$attributeValue, 'is_percent'=>0, 'pricing_value'=>'' )
);
/* Set Associated Products */
$confProduct->setConfigurableProductsData( $simpleProducts );
//print_r( get_class_methods( $confProduct ) );
$confProduct->save();
}
elseif ($_configExist && !in_array($pr->getId(), $new_ids)) {
$new_ids = array();
$current_ids = $_configExist->getTypeInstance()->getUsedProductIds();
$current_ids[] = $pr->getId();
$current_ids = array_unique($current_ids);
foreach($current_ids as $temp_id)
{
parse_str("position=", $new_ids[$temp_id]);
}
Mage::log('inside', null, 'test.txt');
Mage::log($current_ids, null, 'test.txt');
$_configExist->setConfigurableProductsData($new_ids)->save();
}
All works fine with manual product save/update and import csv (it is slow but works). The only thing is, in configurable product, the Attribute Name field is empty. How to set attribute name there?
with magmi you can easily create configurable products, and more awesome stuff
I have found the way. See EDITED 2 section in the question for the solution.

How to load products media gallery along with the collection?

Can anybody give me a hint about how to load product's media gallery along with the collection?
I'm getting the collection like this:
$collection = Mage::getModel('catalog/product')->getCollection()
->addStoreFilter($storeId)
->addAttributeToFilter('status', Mage_Catalog_Model_Product_Status::STATUS_ENABLED);
foreach ($collection as $product) {
var_dump($product->getMediaGalleryImages());
}
But getMediaGalleryImages() returns null. I know that I can load each product separately with $product = Mage::getModel('catalog/product')->load($product->getId()) but I want to avoid this, because it causing unnecessary workload.
In case anyone’s looking for another approach on this, I found this to work (in just one case so no guarantees!):
Be sure to do $collection->addAttributeToSelect(’image’); first, then when looping through the collection products, do:
$attributes = $product->getTypeInstance(true)->getSetAttributes($product);
$media_gallery = $attributes[’media_gallery’];
$backend = $media_gallery->getBackend();
$backend->afterLoad($product); //this loads the media gallery to the product object
Not sure if all of this is necessary but I’m in a hurry. In my particular case I was trying to get the image url using $product->getImageUrl(); and this approach worked for me.
Hope it helps someone else.
I had to do the same recently, fastest method:
class My_Module_Block_Name extends Mage_Catalog_Block_Product_View_Abstract
{
/** #var null|Mage_Catalog_Model_Resource_Eav_Attribute */
protected static $_mediaGalleryBackend = null;
public function getGalleryImages()
{
$product = $this->getProduct();
$this->_getBackend()->afterLoad($product);
$collection = $product->getMediaGalleryImages();
return $collection;
}
/**
* #return Mage_Catalog_Model_Resource_Eav_Attribute
*/
protected function _getBackend() {
if (self::$_mediaGalleryBackend === null) {
$mediaGallery = Mage::getSingleton('eav/config')
->getAttribute(Mage_Catalog_Model_Product::ENTITY, 'media_gallery');
self::$_mediaGalleryBackend = $mediaGallery->getBackend();
}
return self::$_mediaGalleryBackend;
}
}
try this
$collection = Mage::getModel('catalog/product')->getCollection()
->addStoreFilter($storeId)
->addAttributeToSelect(array('image', 'media_gallery'))
->addAttributeToFilter('status', Mage_Catalog_Model_Product_Status::STATUS_ENABLED);
foreach ($collection as $product) {
var_dump($product->getMediaGallery());
}
It can be used directly in loop:
foreach ($collection as $product) {
$product->getResource()->getAttribute('media_gallery')->getBackend()->afterLoad($product);
foreach ($product->getMediaGalleryImages() as $image) {
var_dump($image->debug());
}
}
You are going to have to use:
// Returns the Media Gallery Images
Mage::getModel(’catalog/product’)->load(productid)->getMediaGalleryImages();
Reference: http://www.magentocommerce.com/boards/viewthread/29639/
The secret sauce when working with custom collections involving products is the third parameter of init method... at least it was for me. This way I don't need to load the whole product and run expensive queries.
So, having my custom $product which represents an instance of Mage_Catalog_Model_Product but from my custom collection, I can do:
(string)Mage::helper('catalog/image')->init($product, 'small_image', $product->getImage())
I also needed to add the image attribute to my custom collection, and I did that by adding ->addAttributeToSelect(['image']) to it.
You can also resize your image accordingly:
(string)Mage::helper('catalog/image')->init($product, 'small_image', $product->getImage())->resize($width, $height=null)
Here is a function to add the media gallery to a collection:
// Source: http://www.magentocommerce.com/boards/viewthread/17414/#t141830
public function addMediaGalleryAttributeToCollection(Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection $_productCollection) {
$_mediaGalleryAttributeId = Mage::getSingleton('eav/config')->getAttribute('catalog_product', 'media_gallery')->getAttributeId();
$_read = Mage::getSingleton('core/resource')->getConnection('catalog_read');
$_mediaGalleryData = $_read->fetchAll('
SELECT
main.entity_id, `main`.`value_id`, `main`.`value` AS `file`,
`value`.`label`, `value`.`position`, `value`.`disabled`, `default_value`.`label` AS `label_default`,
`default_value`.`position` AS `position_default`,
`default_value`.`disabled` AS `disabled_default`
FROM `catalog_product_entity_media_gallery` AS `main`
LEFT JOIN `catalog_product_entity_media_gallery_value` AS `value`
ON main.value_id=value.value_id AND value.store_id=' . Mage::app()->getStore()->getId() . '
LEFT JOIN `catalog_product_entity_media_gallery_value` AS `default_value`
ON main.value_id=default_value.value_id AND default_value.store_id=0
WHERE (
main.attribute_id = ' . $_read->quote($_mediaGalleryAttributeId) . ')
AND (main.entity_id IN (' . $_read->quote($_productCollection->getAllIds()) . '))
ORDER BY IF(value.position IS NULL, default_value.position, value.position) ASC
');
$_mediaGalleryByProductId = array();
foreach ($_mediaGalleryData as $_galleryImage) {
$k = $_galleryImage['entity_id'];
unset($_galleryImage['entity_id']);
if (!isset($_mediaGalleryByProductId[$k])) {
$_mediaGalleryByProductId[$k] = array();
}
$_mediaGalleryByProductId[$k][] = $_galleryImage;
}
unset($_mediaGalleryData);
foreach ($_productCollection as &$_product) {
$_productId = $_product->getData('entity_id');
if (isset($_mediaGalleryByProductId[$_productId])) {
$_product->setData('media_gallery', array('images' => $_mediaGalleryByProductId[$_productId]));
}
}
unset($_mediaGalleryByProductId);
return $_productCollection;
}
An example of it's usage below:
$products = Mage::getModel('catalog/product')->getCollection()->addAttributeToSelect('*');
$this->addMediaGalleryToArray($products);

Resources