I have 800 products in my magento store and im trying to change all SKUs, but keep the old ones to another text field. I have found a script that changes all SKUs at once but the problem is that first, i have to insert the text of attribute field SKU, to a new attribute field "old_sku".
How can i update old_sku = sku?
Thanks for any help!
If you do have some PHP knowledge, you could use it to create a PHP script that runs once and replaces all the attribute values. For example, i would do that like so:
<?php
// Magento initialization code; taken from here: http://www.ecomdev.org/2010/06/01/application-bootstrap-in-magento.html
require 'app/Mage.php';
if (!Mage::isInstalled()) {
echo "Application is not installed yet, please complete install wizard first.";
exit;
}
$initializationCode = 'admin';
$initializationType = 'store';
$scope = 'frontend';
Mage::app($initializationCode, $initializationType);
Mage::getConfig()->init();
Mage::getConfig()->loadEventObservers($scope);
Mage::app()->addEventArea($scope);
// Update products
try
{
$products = Mage::getModel('catalog/product')->getCollection();
foreach ($products as $product) {
$product->setOldSku($product->getSku())->save();
}
} catch (Exception $e)
{
echo "Something bad happened: {$e->getMessage()}. Shutting down...";
exit;
}
?>
Just create, let's say, a update_skus.php file within the root directory of your Magento setup (near the index.php file), fill it with the code i've provided and navigate your browser to that file (e. g. http://magento.local/update_skus.php). You should get all the products having their old_sku attribute set exactly to their sku attribute' values.
If you want to keep it really simple then the solution is
a) Add an attribute "old_sku"
b) Export all products
b) Change the CSV - Copy & paste the "sku" column values in "old_sku" and,
d) Import all products
that's it
Hope this helps!!!
Related
let me first explain my problem, I need to change my atribute for free shipping for all the products in a single category. I know how to read atribute value, because I am displaying banner when a product has a free shipping atribute.
Now, what if I have to set these atribute values for all products in a single category?
What will be the best way to achieve that?
It would be very usefull if, I could change values from backend.
I have found, that you can add an atribute for a category, but sometimes, those atributes won't be the same.
I am using Magento 1.9.2
Thank you!
It's not possible to make filter products by category n admin panel. Simple script will make this
<?php
require 'app/Mage.php';
$products = Mage::getModel('catalog/category')->load($category_id)
->getProductCollection()
->addAttributeToSelect('*') // add all attributes - optional
->addAttributeToFilter('status', 1) // enabled
->addAttributeToFilter('visibility', 4); //visibility in catalog,search
foreach($products as $product) {
$product->setAttribute('new value');
$product->save();
}
Just create new php file, put it in main Magento diroctory and run by cli or url.
I actually can add a category via setup script, the thing is for some reason some of the fields doesn't get set properly. Here's is my code
$this->startSetup();
Mage::register('isSecureArea', 1);
$category = Mage::getModel('catalog/category');
$category->setPath('1/2') // set parent to be root category
->setName('Category Name')
->setUrlKey('category-name')
->setIsActive(0)
->setIncludeInMenu(1)
->setInfinitescroll(1)
->setDisplayMode('PAGE')
->setLandingPage($idToCmsBlock)
->setPageLayout('anotherLayoutThanDefault')
->setCustomUseParentSettings(0)
->setCustomLayoutUpdate('<reference name="head"><action method="addCss"><stylesheet>css/somecss.css</stylesheet></action></reference>')
->save();
$this->endSetup();
After running this script, I have a category created with all my value set in the EAVs table.
However the Flat table will be missing displayMode, landingPage, pageLayout, customLayoutUpdate even if I re-index the flat table.
The weird thing is that if I go in the admin, I can see all those fields properly set but if I go in my frontend most of those fields are ignored. I will have to go to the admin, unset those value and reset them for each of them to work properly.
Also let say I use setEnabled(1), my category will be "enable" in the admin but not show up in the frontend.
PS: I have Flat Category activated, if I disable it seems to work fine but if I re-index it still not working.
I finally found it, I'm not sure why but those fields are not showing up properly because they were inserted for the default store (storeId=1) because my script is running in an update script. You need to use the storeId 0.
With this information you would think that the solution would be something like :
$this->startSetup();
Mage::register('isSecureArea', 1);
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
$category = Mage::getModel('catalog/category');
$category->setPath('1/2') // set parent to be root category
->setStoreId(Mage_Core_Model_App::ADMIN_STORE_ID)
->setName('Category Name')
...
->save();
$this->endSetup();
But this code doesn't work either. Indeed after looking into Mage::app() (Mage_Core_Model_App Line 804) I noticed a IF condition that would always return the default store if you're in a setup script.
The trick is to fake that you're not in a setup script, my working solution is:
$this->startSetup();
Mage::register('isSecureArea', 1);
// Force the store to be admin
Mage::app()->setUpdateMode(false);
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
$category = Mage::getModel('catalog/category');
$category->setPath('1/2') // set parent to be root category
->setStoreId(Mage_Core_Model_App::ADMIN_STORE_ID)
->setName('Category Name')
...
->save();
$this->endSetup();
I ran into the same issue when updating a category via a data install script. The solution provided in the accepted answer did work for updating the category, but can be improved upon as follows:
In the solution, the user that triggers the update script is forced to the admin environment. This can be remedied by saving the current store id and switching back at end of the script.
It doesn't seem that adding isSecureArea to the registry or disabling update mode had any use (at least for the use case of updating a category).
I ended up with the following data install script for updating a category (in this example, a category is loaded by name, after which the name is updated):
<?php
$this->startSetup();
//Switch to admin store (workaround to successfully save a category)
$originalStoreId = Mage::app()->getStore()->getId();
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
//update category
$category = Mage::getModel('catalog/category')
->loadByAttribute('name', 'OLD_CATEGORY_NAME');
if ($category) {
$category
->setStoreId(Mage_Core_Model_App::ADMIN_STORE_ID)
->setName('NEW_CATEGORY_NAME')
->save();
}
//Set store to original value
Mage::app()->setCurrentStore($originalStoreId);
$this->endSetup();
?>
Try this
<?php
require_once "../app/Mage.php";
umask(0);
Mage::app('default');
$proxy = new SoapClient("http://127.0.0.1/magento/index.php/api/soap/?wsdl");
$sessionId = $proxy->login($magento_webservices_username, $magento_webservices_passwd);
$data = array('name'=>'Nokia',
'description'=>'',
'meta_description'=>'',
'meta_keywords'=>'',
'default_sort_by'=>'price',
'available_sort_by'=>'price',
'is_active'=>1
);
$newCategoryId = $proxy->call($sessionId, 'category.create', array(3, $data, 1));
echo "Category ID: ".$newCategoryId;
?>
And also have a look Magento create category
Take a look at this. Hope it will help you.
http://inchoo.net/ecommerce/magento/how-to-add-new-custom-category-attribute-in-magento/
I have created multiple categories via installer script.
<?php
$installer = $this;
$installer->startSetup();
Mage::register('isSecureArea', 1);
$category = Mage::getModel('catalog/category');
$category->setPath('1/2/4') // set parent to be root category
->setName('CAT NAME') //Category Name
->setIsActive(1) // Category Status
->setIncludeInMenu(1) // Show in Menu
->setIsAnchor(1) // used for Layered navigation
->setDisplayMode('PAGE') // Product Only
->setPageLayout('one_column') // Page layout
->save();
$installer->endSetup();
I am trying to display a grouped product's price on the product view page in Magento 1.7.0.2, just as it is being displayed in the category product listing ("Starting at: xx.xx"). I thought I could just use
$this->getPriceHtml($_product, true);
to do so because it works the same way in the category product listing, but as everything I tried to do in Magento, it is not that easy because that method doesnt return anything on the product view page.
I looked a little deeper into Magento's code and figured out that the cause of this problem is the product's minimal price data not being set on the product view page ($_product->getMinimalPrice() returns null).
Therefore I did some research on how to load a product's minimal price which brought up ideas like
$_product->getPriceModel()->getMinimalPrice($_product);
which doesnt work because apparently that method was deprecated and removed in one of the last updates or
$priceModel = Mage::getResourceModel('catalogindex/price');
$priceModel->setStoreId(Mage::app()->getStore()->getId());
$priceModel->setCustomerGroupId(Mage::getSingleton('customer/session')->getCustomerGroupId());
$minimalPrices = $priceModel->getMinimalPrices(array($_product->getId()));
$minimalPrice = $minimalPrices[0];
$_product->setData('minimal_price', $minimalPrice['value']);
$_product->setData('minimal_tax_class_id', $minimalPrice['tax_class_id']);
which doesnt work either because the table 'catalogindex_minimal_price' is empty.
So my question is, how does Magento load the minimal price in the category product listing?
I looked a little deeper into Magento's code and tracked down how Magento loads the products of the product list.
When viewing the product list, the product collection is loaded by the model Mage_Catalog_Model_Layer, which adds the minimal price and other stuff to the products in the collection by adding joins to the collection’s SQL, but I have not yet found a model that does the same thing for single products instead of collections.
Because I don’t want to use a direct SQL query, I checked out the CatalogIndex module, but that module seems not to be working at all because all its indexing tables are empty or even corrupted.
$data_grouped = Mage::getModel("catalogindex/data_grouped");
$minimal = $data_grouped->getMinimalPrice(array($_product->getId()), Mage::app()->getStore());
looked good at first but it gives me the following error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'catalog_product_index_price.value' in 'field list'
The CatalogIndex module is either deprecated or I’m just too stupid to enable it.
However, I have now created a workaround in my price.phtml template, which uses the same method to retrieve the minimal price and tax percents as the product list does:
At the beginning of the template I added the following:
$this->setProduct(
Mage::getModel("catalog/product")->getCollection()
->addAttributeToSelect(Mage::getSingleton("catalog/config")->getProductAttributes())
->addAttributeToFilter("entity_id", $this->getProduct()->getId())
->setPage(1, 1)
->addMinimalPrice()
->addFinalPrice()
->addTaxPercents()
->load()
->getFirstItem()
);
which may not be the perfect solution, but it does the job and it does it a little cleaner than iterating over all child products and finding the minimal price that way.
This isn't an answer as much as a big HTML comment on Subsurf's answer. If you're reading this, you might be implementing your own custom module to display a product list. In my case, it's a single page just for wholesalers. My goal was to get a list of my own company's products and give them a list like it was another category. I copied my template's list.phtml to my new content.phtml. But getMinimalPrice() was returning NULL, meaning that when this code calls the getPriceHtml(), price.phtml wasn't showing wholesale pricing.
I did a simple module with index controller and a content.phtml. Using the boilerplate I see all over the net, in the indexController.php file, change:
$block = $this->getLayout()->createBlock(
'Mage_Core_Block_Template',
'b2b',
array('template' => 'b2b/content.phtml')
);
to:
$block = $this->getLayout()->createBlock(
'Mage_Catalog_Block_Product_List',
'b2b',
array('template' => 'b2b/content.phtml')
);
This does a lot of the heavy lifting for you to show the products list correctly.
Now, on to the template file, in my case content.phtml, you get your product collection and then use Subsurf's code in the top of the foreach() which repeats.
$_productCollection = Mage::getModel('catalog/product')
->getCollection()
// ->addAttributeToSelect('*')
// doesn't work ->addAttributeToSelect('special_price')
->addAttributeToSelect('sku')
->addAttributeToFilter('status', 1)
->addAttributeToFilter('visibility', 4)
// http://stackoverflow.com/questions/1332742/magento-retrieve-products-with-a-specific-attribute-value
->addFieldToFilter( array(
array('attribute'=>'manufacturer','eq'=>'143')
, array('attribute'=>'manufacturer','eq'=>'139')
))
;
echo "<p>There are ".count($_productCollection)." products: </p>";
echo '<div class="category-products">';
// List mode
if($this->getMode()!='grid') {
$_iterator = 0;
echo'<ol class="products-list" id="products-list">';
foreach ($_productCollection as $_product) {
?> <li class="item<?php if( ++$_iterator == sizeof($_productCollection) ): ?> last<?php endif; ?>">
<?php
$_product=Mage::getModel("catalog/product")->getCollection()
->addAttributeToSelect(Mage::getSingleton("catalog/config")->getProductAttributes())
->addAttributeToFilter("entity_id", $_product->getId())
->setPage(1, 1)
->addMinimalPrice()
->addFinalPrice()
->addTaxPercents()
->load()
->getFirstItem()
);
echo "Minimal price: ".$_product->getMinimalPrice()."<br>\n";
Since this isn't a single product's page and I'm using other template code, $this->setProduct() didn't do anything for me. I guessed if there was a set, there might be a get, so $_product=$this->getProduct() was the magic my template's price.phtml needed to work properly. Then I noticed I could just assign the Mage:: in setProduct() directly to $_product.
Thanks, Subsurf!!!
There is another way that will still allow you to use $this->getPriceHtml($_product, true); in your template, which then handles all the complex price display rules and puts "Starting at" before grouped product prices.
I'm using this for a custom featured product block. In a block class I have this function:
class MyCompany_Catalog_Block_Product_Featured extends Mage_Catalog_Block_Product_Abstract {
public function setGroupedProductPrice($group_product) {
$prices = array();
foreach ($group_product->getTypeInstance()->getChildrenIds($group_product->getId()) as $ids) {
foreach ($ids as $id) {
$product = Mage::getModel('catalog/product')->load($id);
$prices[] = $product->getPriceModel()->getPrice($product);
}
}
ksort($prices);
$group_product->setPrice(array_pop($prices));
}
}
Then in the template:
<?php
if ($_product->getTypeId() == 'grouped')
$this->prepareGroupedProduct($_product);
echo $this->getPriceHtml($_product, true);
?>
The following does the trick without using a product collection:
$priceResource = Mage::getResourceSingleton('catalogindex/price');
$select = $priceResource->getReadConnection()->select();
$select->from(
array('price_table' => $priceResource->getMainTable())
)
->where('price_table.entity_id = ?', $_product->getId())
->where('price_table.website_id = ?', Mage::app()->getStore()->getWebsiteId())
->where('price_table.customer_group_id = ?', Mage::getSingleton('customer/session')->getCustomerGroupId());
$result = $priceResource->getReadConnection()->fetchRow($select);
This code is adapted from \Mage_CatalogIndex_Model_Resource_Price::getMinimalPrices and made suitable for one single product.
I am working with a magento website. I have used a featured category to display homepage slider products. So when I click on the product it shows featured as a category in the breadcrumb.
Would it be possible not to show featured in the breadcrumb ? I want category name in the breadcrumb for the rest of categories .
Thanks
Ab
actually not getting your question but you can get some idea from here:
in page/html/breadcrumb.phtml file near line 34-36 change, $_crumbInfo['label'] to $_crumbInfo['title']
<?php elseif($_crumbInfo['last']): ?>
<strong><?php echo $this->htmlEscape($_crumbInfo['title']) ?></strong>
then in catalog/block/breadcrumb.php add 2 lines after
$path = Mage::helper('catalog')->getBreadcrumbPath();
$currentCategory = Mage::registry('current_category');
$metaname = $currentCategory['name'];
and change foreach loop like
foreach ($path as $name => $breadcrumb) {
$breadcrumb['title'] = $metaname;
$breadcrumbsBlock->addCrumb($name, $breadcrumb);
$title[] = $breadcrumb['label'];
}
and check it,
hope you get some idea..
Why no simpler than that?
Try to use CSS. Your category will have an automatic and specific class for it. For example:
<li class="category4">
<strong>ARCHERY HUNTING</strong>
</li>
In this piece of code, I have a category that I created, called "Archery hunting". The code auto-created the class="category4", So, only write on your CSS:
.category4 strong { display: none; }
And it will hide only that category.
Instead of using
$_product->getProductUrl()
to fetch URL, use this:
$_product->unsRequestPath()->getUrlInStore(array('_ignore_category' => true))
Then you need to unset last visited category id at the end of your featured block:
Mage::getSingleton('catalog/session')->setLastVisitedCategoryId('');
This is all because key part for forming breadcrumbs is the following code:
$categoryId = $params->getCategoryId();
if (!$categoryId && ($categoryId !== false)) {
$lastId = Mage::getSingleton('catalog/session')->getLastVisitedCategoryId();
if ($product->canBeShowInCategory($lastId)) {
$categoryId = $lastId;
}
}
basically, current category is determined by either URL params (hence the modified URL call), or through the session object (hence the removal of last visited category id)
so, to recapitulate, in your Featured block, instead of regular productUrl call, use the one I provided, and at the end of your featured product block listing, remove the lastVisitedCategoryId using the code I gave you
My Magento site has a product which has a few Custom Options, one text, one file upload and four drop down lists.
The design of the site dictates that I need to show these options throughout the product view page and not all in one group.
Is there a function that I can call to return the HTML of a single Custom Option?
There are ways to do this that are tantamount to cheating.
Your shop requires javascript to operate and there is a lot you can do with Prototype before the page renders, by using the on dom:loaded event. You can attach your custom options to wherever you want in the DOM, or you can hide them and put something else where you want it on the page that updates the form element. You may want to do this if you have to capture a colour name but don't want to put oodles of colours on every product - a textbox can go on the product and your control can write to it.
The benefit of some $$('cheating') is that you don't have to go too deep into Magento code for what is a 'design consideration'.
I didn't understand correctly about group. If you mean category then ;
create a new attribute set which this attribute set should contain attributes that you want to show. After that, when you create a product, select this attribute set instead of default. So that, only this attributes will be available in the specified products.
Try the following code snippets ( don't forget to change "attribute_code")
Let say, you want to show Multi Select list in your product page, in that case :
$selectArray = $this->getProduct()->getAttributeText('YOUR_ATTRIBUTE_CODE');
$endOfArray = end($selectArray);
echo "<ul class='set-some-class'>";
foreach($selectArray as $selectionItem) {
echo "<li> . $selectionItem";
if($selectionItem != $endOfArray) {
echo "</li>\n";
} else {
echo "</ul>";
}
}
For page other than product view page, in that case:
$attribute = Mage::getModel('catalog/product')->getAttribute('catalog_product', 'YOUR_ATTRIBUTE_CODE');
$options = $attribute->getSource()->getAllOptions(true, true);
$lastOption = end($options);
echo "<ul class='set-some-class'";
foreach($options as $option) {
echo $option['label'];
if($option != $lastOption) {
echo "<li>\n";
} else {
echo "</ul>";
}
}