How to find out master product of simple product? - php

How can I find out, if a simple product is part of a configurable product and then get the master product? I need this for the product listing.
Just found out:
$_product->loadParentProductIds();
$parentIds = $_product->getParentProductIds();

Let's say that you have your simple product's Product ID.
To get all the parent configurable product IDs of this simple product, use the following code:-
<?php
$_product = Mage::getModel('catalog/product')->load(YOUR_SIMPLE_PRODUCT_ID);
$parentIdArray = $_product->loadParentProductIds()
->getData('parent_product_ids');
if(!empty($parentIdArray)) {
// currently in the master configurable product
print_r($parentIdArray); // this prints all the parent product IDs using your simple product.
}
?>
I suppose this should get you going.

For Magento 1.4.2 and above use the following method instead:
$configurable_product_model = Mage::getModel(‘catalog/product_type_configurable’);
$parentIdArray = $configurable_product_model->getParentIdsByChild($simple_product_id);

After version 1.4.2.0 the loadParentProductIds() and getParentProductIds() methods are deprecated. Don't ask me why. Personally I kind of liked those methods. So I've reintroduced them to my local Mage classes. This is how:
Copy
app/code/core/Mage/Catalog/Model/Product.php
to
app/code/local/Mage/Catalog/Model/Product.php
and change the loadParentProductIds() method, found around line 1349 to:
public function loadParentProductIds()
{
return $this->_getResource()->getParentProductIds($this);
}
This piece of code will query its resource for its parent product ids. For this to work we'll need to rewrite the getParentProductIds() method in the resource class.
So copy:
app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product.php
to
app/code/local/Mage/Catalog/Model/Resource/Eav/Mysql4/Product.php
Find the deprecated getParentProductIds() method. Should be somewhere around line 535. Overwrite it with the pre 1.4.2.0 code:
public function getParentProductIds($object){
$childId = $object->getId();
$groupedProductsTable = $this->getTable('catalog/product_link');
$groupedLinkTypeId = Mage_Catalog_Model_Product_Link::LINK_TYPE_GROUPED;
$configurableProductsTable = $this->getTable('catalog/product_super_link');
$groupedSelect = $this->_getReadAdapter()->select()
->from(array('g'=>$groupedProductsTable), 'g.product_id')
->where("g.linked_product_id = ?", $childId)
->where("link_type_id = ?", $groupedLinkTypeId);
$groupedIds = $this->_getReadAdapter()->fetchCol($groupedSelect);
$configurableSelect = $this->_getReadAdapter()->select()
->from(array('c'=>$configurableProductsTable), 'c.parent_id')
->where("c.product_id = ?", $childId);
$configurableIds = $this->_getReadAdapter()->fetchCol($configurableSelect);
return array_merge($groupedIds, $configurableIds);
}
Now you once again can do this:
$_product->loadParentProductIds()->getData('parent_product_ids');
Hope this helps you out!

Related

Creating Multiple Custom Attibutes For Product with google-api-php-client

According to that answer https://support.google.com/merchants/answer/4588281?hl=en-GB
if I want set multiple promotions ids for the product with the API I can specify multiple lines of:
<sc:attribute name="promotion_id">PROMOTION_ID</sc:attribute>
I am using this lib https://github.com/google/google-api-php-client
My question is how can i do it with this library. Should I use custom attributes? for example.
$feed_entry = new Google_Service_Content_Product();
$promotions_ids = array (20,21,22);
foreach ($promotions_ids as $promotion_id ) {
$promotion = new Google_Service_Content_ProductCustomAttribute();
$promotion->setName('promotion_id');
$promotion->setValue($promotion_id);
$feed_entry->setCustomAttributes($promotion);
}
But that would just set this attribute over again for different ids. I am not even sure if I am doing this in a right way. Probably missing something. The full code example would be really helpful.
I couldn't find a definitive code sample for PHP. That being said, if you look at API libraries for other languages you find that:
For Java it uses a List<ProductCustomAttribute>:
public Product setCustomAttributes(java.util.List<ProductCustomAttribute> customAttributes)
Source
For JavaScript it uses a map:
setCustomAttributes(map)
setCustomAttributes({ 'size': 'Large', 'color': 'Green' })
Source
Conclusion:
there's a very good chance the PHP method in question uses an array of Google_Service_Content_ProductCustomAttribute objects:
public function setCustomAttributes($customAttributes)
$feed_entry = new Google_Service_Content_Product();
$promotions_ids = array (20,21,22);
$customAttributes = array();
foreach ($promotions_ids as $promotion_id ) {
$promotion = new Google_Service_Content_ProductCustomAttribute();
$promotion->setName('promotion_id');
$promotion->setValue($promotion_id);
$customAttributes[] = $promotion;
}
$feed_entry->setCustomAttributes($customAttributes);
Try it!

Adding custom option to order line

I'm currently trying to add a custom option to a specific orderline on add to cart via the following:
public function addToPackageQuote()
{
$cart = Mage::getSingleton("checkout/cart");
$quote = Mage::getSingleton("checkout/session")->getQuote();
$packageId = Mage::getModel('MyTuxedo_OPP/Package')->checkPackageId();
$products = $this->sortArray();
foreach ($products as $productInfo) {
try {
$split = explode(",", $productInfo);
$_product = Mage::getModel('catalog/product')->load($split[0]);
if($_product->isConfigurable()) {
$simpleId = $this->getConfigurableSimple($split[1],$split[3],$split[0]);
} else {
$simpleId = $split[0];
}
$product = Mage::getModel('catalog/product')->load($simpleId);
$options = new Varien_Object(array(
"qty" => 1,
"custom_options" => array(
"package" => $packageId,
"packageName" => Mage::helper('MyTuxedo_OPP')->getPackageName()
)
));
$quote->addProduct($product, $options);
$this->_getSession()->setCartWasUpdated(true);
$quote->save();
} catch (Exception $e) {
echo $e->getMessage();
}
$this->addFreeItems();
}
$cart->save();
unset($_SESSION['products']);
unset($_SESSION['productId']);
$cart->save();
// Let's unset all the package sessions (apart from a few that are needed!).
$this->kill();
}
This method is completely seperate from the generic add to cart handler, and is used purely in a packages system so that it adds simple products exclusively (also breaks down configurables super attribute to find the simple product too).
These simple products have no custom options attached to them in the Magento backend, nor is it a goal to add custom options to the product itself. What I would like to do is attach custom options to the order-line that is then transferred over to the order if a purchase is made. So effectively data that is added at the add to cart method and no where else!
The add to cart method works as expected it's just not including the custom options I am trying to attach. I have also tried defining the options object as simply:
$options = new Varien_Object(array(
"qty" => 1,
"package" => $packageId,
"packageName" => Mage::helper('MyTuxedo_OPP')->getPackageName()
)
The above info, not including qty is not in the orderline object at all, and I can't seem to work out where to move on from here.
Endlessly googling at the moment so some help would be most appreciated!!
I do appreciate I’m instantiating the product model object twice in this, however the plan is to just get it working then optimise! :)
You have to set the custom options for the product before adding it to cart.
$product->setCustomOptions($options);
The in Mage_Sales_Model_Quote::_addCatalogProduct() the custom options will be added to the cart item.
See also here: http://www.magentocommerce.com/boards/viewthread/49659/
By the way: Your code may be pretty slow because you are loading products twice in a foreach loop. You should consider some refactoring by using the product collection instead. Also it looks kind of hackish to directly access the $_SESSION variable here. You could rather use the Checkout Session for that (Mage::getSingleton('checkout/session')).
I have now resolved this, after much headache. You can add a custom option to the cart and not have to instantiate the product object and save a custom option to do this, it can be done via tacking onto an observer, and pulling the quote items.
After tacking onto: sales_quote_add_item
I then used:
public function addCustomData($observer) {
$event = $observer->getEvent();
$quote_item = $event->getQuoteItem();
$quote = $session->getQuote();
$quote_item->addOption(array("product_id" => $quote_item->getProduct()->getId(),
"product" => $quote_item->getProduct(),
"code" => 'PackageId',
"value" => Mage::getModel('MyTuxedo_OPP/Package')->checkPackageId()
));
$quote->save();
}
It is most important to include the product object and id, as the function doesn't use the loaded object for some reason.
You can then get at the object via:
$_item->getOptionByCode('PackageId')->getValue();
Quick piece of handy info, if it dumps a stack trace in front of you it can't find the defined option, lose the getValue() (if using var_dump) function to see if you are getting a null value, otherwise xdebug will give you a ton of hints to get around it.

Virtuemart 2 - Add the product image to the "add to cart"-popup

I've been looking for this like everywhere now ;)
I want to add the product image to the popup, but I can't figure out how to achieve this!
I've been searching for hours and hours now and next to that tried to code this myself but it won't work.
So now I'm asking for help... if anyone has some ideas on this please let me know.
Afaik there's more people on the net that would like to see a "add to cart"-popup with some more informations given on it.
Sincerly Thomas
I just recently customised the add to cart popup on a site myself. The file you need to edit is components/com_virtuemart/controllers/cart.php (the function is called addJS if I remember correctly).
You can find the API documentation for VirtueMart here: http://docs.virtuemart.net/api-vm2/ however I wrote my own plugin to fetch the VM data.
Then you can just use standard PHP rather than getting your head round the VM API.
If you decide to do it my way you can call custom classes from your plugin and output the image like so:
$cart_image = plgMyCoolPlugin::_getImage($this->product->virtuemart_product_id);
echo '<img src='.$cart_image.'/>';
Remember you need to import your plugin type if you don't make it a system plugin:
JPluginHelper::importPlugin( 'mynewplugintype' );
Here's the function I use in my plugin:
function _getImage($id)
{
$db =& JFactory::getDBO();
$sql = " SELECT
b.`file_url`
FROM
".$db->nameQuote('#__virtuemart_product_medias')." AS a
INNER JOIN
".$db->nameQuote('#__virtuemart_medias')." AS b ON a.`virtuemart_media_id` = b.`virtuemart_media_id`
WHERE
a.".$db->nameQuote('virtuemart_product_id')." = ".$id."
AND
b.".$db->nameQuote('file_mimetype')." = 'image/jpeg'
AND
b.".$db->nameQuote('file_type')." = 'product'
AND
b.".$db->nameQuote('file_is_forSale')." = '0'";
$query = $db->setQuery($sql);
$row = $db->loadResultArray();
if($db->getErrorNum()) {
JError::raiseError( 500, $db->stderr());
}
if(empty($row)) $row[] = JURI::base().'images/defaultimage.jpg';
return $row;
}
Hope this helps :)

Get product atribute value in magento

Hi i have got the maximum elements of products using below code but it doesn't show the size attribute of my product, the size attribute is visible on front-end but i cant understand why it is not printing with this code
<?php
ob_start();
session_start();
ini_set('display_errors', 1);
//for order update
include '../../../../app/Mage.php';
Mage::app('default');
echo '<pre>';
if(isset($_REQUEST['productid'])){
$productId = $_REQUEST['productid'];
}else{
$productId = '12402'; // product ID 10 is an actual product, and used here for a test
}
$product = Mage::getModel('catalog/product')->load($productId); //load the product
//$product_id = $product->getId();
//$created_at = $product->getcreated_at();
//$description = $product->getdescription();
//$short_description = $product->getshort_description();
//$sku = $product->getsku();
//$size_fit = $product->getsize_fit();
//$style_ideas = $product->getstyle_ideas();
//$name = $product->getname();
//$price = $product->getprice();
//$stocklevel = (int)Mage::getModel('cataloginventory/stock_item')->loadByProduct($product)->getQty();
If its the size_fit attribute (i'm guessing that because its the only size attempt in your code..) use $product->getSizeFit(). For just size use $product->getSize(). When this is not returning anything, please post the attribute installer if you have one. Mufadall his answer is also correct but judging your code you are just using wrong syntax.
Basicly according to the magic get method the first letter is turned into a capital and all other letters after an underscore.
Ex.: To fetch my_sample_attribute use getMySampleAttribute().
getData('my_sample_attribute') would also be an option but you shouldn't make a habbit of doing that because in some cases, for some attributes getData('attribute') returns a different value then getAttribute()....
$product->getData($attribute_code);
will return you the actual attribute value. For attribute with type dropdown it will return option id
$product->getResource()->getAttribute($attribute_code)->getFrontend()->getValue($product);
will return actual value
You can use this:
$product->getData('Your Attribute ID');
Go to Size attribute and check for Drop Down used in product listing if it set to No then set it to Yes, after that you can get your size attribute with other product attribute
You can use the getters, or getData();
The getter is set in magento with the magic __get() method, and you can use it in the following way:
$product->getDescription() // ( to get description attribute)
$product->getShortDescription() // (to get short_description attribute)
So basically you explode the attribute with underscores, and capitalize the words, and you will get what you need to put after "get".
Here is something very useful I use all the time
Zend_Debug::dump($product->getData());
This gets you all the data you have to work with. If you are missing data, it means it's not loaded.
Good luck!

How to add a category to Magento via Setup script?

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();

Categories