Programmatically change product attribute at store view level - magento

I'm sorry if this question is trivial but I've been struggling to find what I am doing wrong here. I am trying to change the value of an attribute on a store view level but the default is also changed whereas it shouldn't be. Of course, this attribute is set up to be "store-view-scoped". To keep it simple, I've tried with the product name. No success.
Below are unsuccessful tests I've tried...
Do you see what I am doing wrong here?
Many thanks.
My tries :
$product = Mage::getModel('catalog/product')->load(PRODUCT_ID);
$product->setStoreId(STORE_ID)->setName('new_name')->save();
$product = Mage::getModel('catalog/product')->load(PRODUCT_ID);
$product->setStoreId(STORE_ID)->setStore(STORE_CODE)->setName('new_name')->save();
$product = Mage::getModel('catalog/product')->load(PRODUCT_ID);
$product->setStoreId(STORE_CODE)->setName('new_name')->save();
$product = Mage::getModel('catalog/product')->setStoreId(STORE_ID)->load(PRODUCT_ID);
$product->setName('new_name')->save();
$product = Mage::getModel('catalog/product')->setStoreId(STORE_ID)->load(PRODUCT_ID);
$product->setStoreId(STORE_ID)->setName('new_name')->save();
I even tried by adding the line below before the product model load...
Mage::app()->setCurrentStore(STORE_ID);

So here is the complete snippet to change attribute value for a specific product attribute on a specific store view. Example with the product name :
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
$product = Mage::getModel('catalog/product')->load(PRODUCT_ID);
$product->setStoreId(STORE_ID)->setName('my_new_product_name')->save();
And as an additional answer, one could be interested in changing the attribute value to the default one. In this case, the argument 'false' must be passed to the setAttribute :
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
$product = Mage::getModel('catalog/product')->load(PRODUCT_ID);
$product->setStoreId(STORE_ID)->setName(false)->save();

You need to set the current store to admin at the top of your code block:
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);

note when loading product with data for some store view, also default values get loaded. saving such product will save default values as store values (thus unset "Use Default Value" for fields)
i ended up with following function to clean-up product data from default values
public static function _removeDefaults($item) {
static $attributeCodes = null;
if($attributeCodes == null) {
$attributes = Mage::getSingleton('eav/config')
->getEntityType(Mage_Catalog_Model_Product::ENTITY)->getAttributeCollection();
$attributeCodes = array();
foreach($attributes as $attribute) {
$ac = $attribute->getAttributeCode();
if(in_array($ac, array('sku','has_options','required_options','created_at','updated_at','category_ids'))) {
continue;
}
$attributeCodes[] = $ac;
}
}
foreach($attributeCodes as $ac) {
if(false == $item->getExistsStoreValueFlag($ac)) {
$item->unsetData($ac);
}
}
}
remember to send only product loaded for some store view

Related

Magento 2.3 graphql get custom attribute option values

I’m pretty frustrated with the graphql api of Magento. How is it not possible to receive the values of a custom attribute. I mean it’s easy to make a custom select-option attribute and making it available through graphql but you are only getting the integer value.
What’s the best procedure to following
1. Query the complete attribute to get the value
2. Extending the graphql schema (this involves a developer every time the client changes something)
3. Am I missing some functionality inside the graphql endpoints to Fix this?
From Native GraqpQl we cannot get the expected result.But we can write a custom module with the graphql and achieve it.What my suggestion is get the product detail by sku using _productRepository->get($sku);. This will return the entire product details.So you can get the attribute data by using $attributes = $_product->getAttributes(); Here is my data provider file.
/**
* #params string $sku
* this function return all the product data by product sku
**/
public function getProductBySku($sku)
{
return $this->_productRepository->get($sku);
}
/**
* #params int $id
* this function return all the word of the day by id
**/
public function getAttributesBySku( $sku ){
$_product = $this->getProductBySku($sku);
$attributes = $_product->getAttributes();// All Product Attributes
$attributes_data = [];
$x=0;
foreach ($attributes as $attribute) {
if($attribute->getIsUserDefined()){ // Removed the system product attribute by checking the current attribute is user created
$attributeLabel = $attribute->getFrontend()->getLabel();
$attributeValue = $attribute->getFrontend()->getValue($_product);
if($attribute->getAttributeCode()=="language"){
$attributeLabelAndValue = $attributeLabel." - ".$attributeValue;
$attributes_data[$x]['atr_data'] = $attributeLabelAndValue;
}
}
$x++;
}
return $attributes_data;
}
This code will return the need
$attribute->getFrontend()->getLabel(); this will return the label and
$attribute->getFrontend()->getValue($_product); this will return the value.
To check the entire graphQl query and resolver file kindly view How to get product attribute value, label using GraphQl in Magento 2.3?
Hope this will help you.
You can try creating custom graphql attribute with custom resolver.
$product = $this->_productRepository->getById($value['entity_id']);
$data = array();
foreach ($args['fields'] as $fi) {
$att = $product->getResource()->getAttribute($fi);
if (isset($att) && $att) {
if (in_array(
$att->getFrontendInput(),
['multiselect', 'select']
)) {
$data[$fi . '_label'] = $product->getAttributeText($fi);
}
$data[$fi] = $product->getData($fi);
}
}
return json_encode((object) $data);
which should display all provided attributes with their labels.
"sku": "testProduct",
"fabric": 60,
"work": 65,
"dynamicAttributes": "{
"fabric_label":"Pure Silk",
"fabric":"60",
"work_label":"Tanchoi",
"work":"65"
}",
Check out entire module here

How to programmatically disable product for all store-view in Magento?

I want to disable product programmatically for all store view. Please help me
I tried with the following... but no luck
$storeId = 0;
Mage::getModel('catalog/product_status')->updateProductStatus($product_id, $storeId, Mage_Catalog_Model_Product_Status::STATUS_DISABLED);
Firstly $storeId=0 is default store id for admin if you want disable product for all store view then you can set $storeId=Mage:app()->getStoreId()// this is for current store id
after that you can disable all product
$product_id=1;
$storeId=Mage::app()->getStoreId();
Mage::getModel('catalog/product_status')->updateProductStatus($product_id, $storeId, Mage_Catalog_Model_Product_Status::STATUS_DISABLED);
EDIT
This is for all store view i think this is the dirty way to achieve this
<?php
$allStores = Mage::app()->getStores();
foreach ($allStores as $_eachStoreId => $val)
{
$_storeId[] = Mage::app()->getStore($_eachStoreId)->getId();
}
for($i=0;$i<count($_storeId);$i++)
{
$product_id=1;
$storeId=$_storeId[$i];
Mage::getModel('catalog/product_status')->updateProductStatus($product_id, $storeId, Mage_Catalog_Model_Product_Status::STATUS_DISABLED);
}
?>
Let me know if you have any query
By default the scope of status attribute is set to store , if we will set it to global under manage attributes , than we can update status for all store views with below code.
$loadproduct = Mage::getModel("catalog/product")->load("product_id");
$loadproduct->setStatus(2);
$loadproduct->save();
thanks
There's a much shorter way than in the answer of Keyur Shah:
foreach (Mage::app()->getStores() as $store) {
Mage::getModel('catalog/product_status')->updateProductStatus($productId, $store->getId(), Mage_Catalog_Model_Product_Status::STATUS_DISABLED);
}

How to update an attribute value in Magento?

I've created an attribute called "popularity" which will be used to organize the catalog by most viewed products. The idea is get its value on product view template (view.phtml on my theme) and increment that value and update it, however I don't know how to make this update, I mean, how to save the new value incremented into database. I've put this on the product view page, take a look:
$popularity = $_product->getData('popularity');
$popularity++;
The point is that $popularity is not being saved with the new value into database. How can I save that value?
I put the code below on product page template (mytheme/template/catalog/product/view.phtml) but is not working:
$from_date = '2010-01-01';
$to_date = now();
$product_ids = $_product->getId();
$viewed = Mage::getResourceModel('reports/product_collection')->addViewsCount($from_date, $to_date)->addFieldToFilter('entity_id', $product_ids);
foreach($viewed as $view) {
$count_views = $view->getData('views');
$product_model->setData('popularity', $count_views)->getResource()->saveAttribute($product_model, $count_views);
}
Thanks for help!
Try this:
$popularity = $_product->getData('popularity');
$popularity++;
Mage::getSingleton('catalog/product_action')
->updateAttributes(array($_product->getId()), array('popularity', $popularity), 0);
This will work, if the scope of your attribute is GLOBAL. If it's something else then you can use this:
Mage::getSingleton('catalog/product_action')
->updateAttributes(
array($_product->getId()),
array('popularity', $popularity),
Mage::app()->getStore()->getId()
);

How to check if attribute exist in product attribute set? Magento

How to check if attribute exist in product attribute set?
I need to know if a product has an attribute for its set of attributes.
I get the attribute with:
$attrPricekg = Mage::getModel('catalog/product')->load($_product->getId())->getPricekg();
If attribut exist in product attribute set, $attrPricekg display: set value for the product
or 0 if no value set for the product.
If the attribute does not exist in product attribute set, $attrPricekg display 0. This is my problem.. I need to avoid this, I want to check that the attribute does not exist for that product.
Thanks.
now I'll provide an answer which works regardless!
$product = Mage::getModel('catalog/product')->load(16);
$eavConfig = Mage::getModel('eav/config');
/* #var $eavConfig Mage_Eav_Model_Config */
$attributes = $eavConfig->getEntityAttributeCodes(
Mage_Catalog_Model_Product::ENTITY,
$product
);
if (in_array('pricekg',$attributes)) {
// your logic
}
To check if a specific attribute exists in product, it should return true even if the attribute has the value 'null'.
One way that works is:
$attr = Mage::getModel('catalog/resource_eav_attribute')->loadByCode('catalog_product',$code);
if (null!==$attr->getId())
{
//attribute exists code here
}
It can also of course be written in one line:
if(null!===Mage::getModel('catalog/resource_eav_attribute')->loadByCode('catalog_product','attributecode_to_look_for')->getId()) {
//'attributecode_to_look_for' exists code here
}
Found it and modified a bit on:
https://github.com/astorm/Pulsestorm/issues/3
May be this way is better for you:
$attribute = Mage::getModel('catalog/product')->load($productId)->getResource()->getAttribute($attributeCode);
if ($attribute && $attribute->getId()) { ... }
Also you may try
$attributes = $product->getAttributes();
But you may check all in attribute collection:
$entityTypeId = Mage::getModel('eav/entity')
->setType('catalog_product')
->getTypeId();
$attributeId = 5;
$attributeSetName = 'Default';
$attributeSetId = Mage::getModel('eav/entity_attribute')
->getCollection()
->addFieldToFilter('entity_type_id', $entityTypeId)
->addFieldToFilter('attribute_set_name', $attributeSetName)
->addFieldToFilter('attribute_id', $attributeId)
->getFirstItem();
May be source code need some corrections, but I think you will understand the idea.
See some more examples here, also - http://www.blog.magepsycho.com/playing-with-attribute-set-in-magento/
EDIT: this is not the correct answer.
$product->offsetExists('pricekg');
See Varien_Object::offsetExists() (link).

How to check if a Magento product is already added in cart or not?

I want to show popup when a product is first added to cart in Magento and don't want to show a popup if the product was added again or updated.In short, I want to know product which is going to be added in the cart is First occurence or not?
The answer largely depends on how you want to deal with parent/child type products (if you need to).
If you are only dealing only with simple products or you have parent/child type products and you need to test for child id's then:
$productId = 1;
$quote = Mage::getSingleton('checkout/session')->getQuote();
if (! $quote->hasProductId($productId)) {
// Product is not in the shopping cart so
// go head and show the popup.
}
Alternatively, if you are dealing with parent/child type products and you only want to test for the parent id then:
$productId = 1;
$quote = Mage::getSingleton('checkout/session')->getQuote();
$foundInCart = false;
foreach($quote->getAllVisibleItems() as $item) {
if ($item->getData('product_id') == $productId) {
$foundInCart = true;
break;
}
}
EDIT
The question was asked in a comment as to why setting a registry value in controller_action_predispatch_checkout_cart_add is not available to retrieve in cart.phtml.
Essentially registry value are only available through the life of a single request - you are posting to checkout/cart/add and then being redirected to checkout/cart/index - so your registry values are lost.
If you would like to persist a value across these then you can use the session instead:
In your observer:
Mage::getSingleton('core/session')->setData('your_var', 'your_value');
To retrieve the value
$yourVar = Mage::getSingleton('core/session')->getData('your_var', true);
The true flag being passed to getData will remove the value from the session for you.
In order check if the product is already in cart or not, you can simply use the following code:
$productId = $_product->getId(); //or however you want to get product id
$quote = Mage::getSingleton('checkout/session')->getQuote();
$items = $quote->getAllVisibleItems();
$isProductInCart = false;
foreach($items as $_item) {
if($_item->getProductId() == $productId){
$isProductInCart = true;
break;
}
}
var_dump($isProductInCart);
Hope this helps!

Resources