I want to show the quantity sold on the frontend for configurable products. I have this code already that works perfect for simple products. But for configurable products always shows 0.
How Can I update so it works for both, simple and configurable. Also will be cool to hide it when sold quantity is 0.
<?php
$sku = nl2br($_product->getSku());
$product = Mage::getResourceModel('reports/product_collection')
->addOrderedQty()
->addAttributeToFilter('sku', $sku)
->setOrder('ordered_qty', 'desc')
->getFirstItem();
echo 'Already Bought '.(int)$product->ordered_qty; ?>
You might be having problems because product options can change the specific SKU for an item in a quote/order. Try just looking it up product ID instead.
Something like (I haven't tried this code to test it):
<?php
$product = Mage::getResourceModel('reports/product_collection')
->addOrderedQty()
->addAttributeToFilter('id',$_product->getID())
->setOrder('ordered_qty', 'desc')
->getFirstItem();
$sold = (int)$product->ordered_qty;
?>
Then wherever you want it to show up:
<?php
if ($sold > 0) {
echo "Already sold $sold times.";
}
?>
Or however you want to display it.
EDIT BELOW
I'll leave the above for consistency, but you're right, it caused the same error for me:
Fatal error: Call to a member function getBackend() on a non-object in ~app/code/core/Mage/Eav/Model/Entity/Abstract.php on line 816
That annoyed me, so I dug in and didn't be lazy this time, and actually wrote some working example code. I learned something important during this, too - be sure you always have addOrderedQty() before addIdFilter(), or your collection will just ignore that filter entirely. Thanks, Magento.
Anyway, this little self-contained example will get the Ordered Quantity and print it with the product ID, it should be pretty clear what's going on in it.
<?php
require_once '<path_to_magento_root>/app/Mage.php';
Mage::app('default');
$p = Mage::getResourceModel('reports/product_collection')
->addOrderedQty()
->addIdFilter($argv[1])
->getFirstItem();
echo $p->getId().": ".$p->ordered_qty.PHP_EOL;
?>
Run it like this:
php test.php 131
And you get output like this:
131: 103.0000
Hope this helps a little more than my first attempt.
Related
Too explain more, I have a shopping website where many of the products are not rated but I would like to show some default rating like 3 stars or 5 stars for each product which is not rated. The purpose is to show ratings for each products in any possible way. Is it possible? Please let me know how can I do it in the best easiest way.
With some search, Here is what I found :
PHP Method WC_Product::set_average_rating, woocommerce Code Examples
So, I suppose you could do something like this :
foreach ($products as $product) {
$count = $product->get_rating_count();
if (!$count) {
$average = 0.65;
}
$product->set_average_rating($average);
$data_store = $product->get_data_store();
$data_store->update_average_rating($product);
}
/!\ not tested.
Hope it helps.
I've set an observer for sales_quote_add_item in order to clear the cart whenever a certain product is going to be added (it's only supposed to be ordered alone).
I'm just not sure on how to get the product ID of the product that is about to get added. With some trial & error I've come up with this:
$tmp = $observer->getEvent()->getQuoteItem()->getData();
echo $tmp['product_id'];
Which seems to be quite an ugly solution. I'm sure there is some shortcut or proper function to call for this, any ideas?
Your solution is good enough
$productId = $observer->getEvent()->getQuoteItem()->getProductId();
You may load product after if is needed
$product = Mage::getModel('catalog/product')->load($productId);
Use the following code to get product id of quote item data
$cart = Mage::getModel('checkout/cart')->getQuote();
foreach ($cart->getAllItems() as $item)
{
$productId = $item->getProduct()->getId();
}
Hope this helps to you.
I would like to add 3 links to random products on the .../template/catalog/product/view.phtml template.
Based on list.phtml, I tried adding:
<?php
$_productCollection=$this->getLoadedProductCollection();
foreach ($_productCollection as $_randomProduct) {
echo $_randomProduct->getProductUrl();
}
?>
But I'm not getting a list back of URL's. How can I get an array of other product's links and images?
That code lets you down because $this in view.phtml is not the same $this as in list.phtml.
If you wanted to get some products relevant to the current product's category try this:
$_productCollection = $_product->getCategory()->getProductCollection();
Alternatively if you didn't care where they come from:
$_productCollection = Mage::getResourceModel('catalog/product_collection')
->setStore(Mage::app()->getStore());
To get the randomness this little trick will help:
$_productCollection->setPageSize(3)
->getSelect()->order('RAND()');
Now you can use the collection in a foreach loop.
I have the following code:
$_productCollection = $this->getLoadedProductCollection();
foreach ($_productCollection as $_product)
{
if ($_product->_data['type_id'] == 'configurable')
{
...
}
}
While it does what it's supposed to do, it greatly slows down page load time. Is it possible to load only configurable products and remove the check for 'configurable'? The store has 12000 products, about 700 are configurable and the rest are child simple products.
I found the following code which returns all configurable products. I need only the products within the current category:
$collectionConfigurable = Mage::getResourceModel('catalog/product_collection')
->addAttributeToFilter('type_id', array('eq' => 'configurable'));
The problem with getLoadedProductCollection() is it's already loaded - the products' data has already been retrieved from the database. Just using the current category's product collection isn't good enough either, that will ignore the "layers" (attribute filters). The trick is to remove the loaded products from the list first.
// First make a copy, otherwise the rest of the page might be affected!
$_productCollection = clone $this->getLoadedProductCollection();
// Unset the current products and filter before loading the next.
$_productCollection->clear()
->addAttributeToFilter('type_id', 'configurable')
->load();
print_r($_productCollection) has it's issues too, you're not just outputting the products but also all details of the resource that is the database connection, and cached values, and the products' individual resources, and so on...
In this case I think you would be happier with:
print_r($_productCollection->toArray())
All those solutions didn't work for me, try this:
$_productCollection1 = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('*')
->addAttributeToFilter('type_id','configurable');
foreach ($_productCollection1 as $product1) {
echo $product1->getName();
...
}
It works but don't know if it's correct (I'm new to Magento). Let me know please.
The way you're doing this requires all products to be loaded before you parse through and filter them. This is probably closer to what you're looking for:
$_productCollection = $this ->getLoadedProductCollection()
->addAttributeToFilter('type_id','configurable');
Try following
$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToFilter('type_id','configurable');
foreach($collection as $product)
{
}
For loading configurable and simple as well try
$collection->addAttributeToFilter('type_id', array('in' => array('configurable','simple')));
Here is the code for getting only configurable products:
$Config_products = Mage::getModel('catalog/product')->getCollection()
->addAttributeToFilter('type_id','configurable');
Use \Magento\Catalog\Model\ResourceModel\Product\Collection $_productcollection,
public function getConfigProducts() {
$configproducts = $this->_productcollection;
$configproducts->addAttributeToSelect('*');
$configproducts->addAttributeToFilter('status',\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED);
$configproducts->addAttributeToFilter('show_in_price_page', array('eq' => 1));
$configproducts->addAttributeToFilter('type_id', array('eq' => "configurable"));
return $configproducts;
}
If you change Visibility of simple product to "Not Visible Individually", Magento will not load it to display in product list page.
I have the following code to grab a list of Products
$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToSelect('name')
->addAttributeToFilter("category_ids", array('finset'=>$this->category_id));
foreach($collection as $product) {
echo $product->getName();
}
My question is, how can I NOT echo products that are 'simple' but belong to a parent 'configurable' product. (for example don't show "Red Shirt Medium" as it belongs to "Red Shirt")
I have worked out that this association lives in 'catalog_product_super_link' but I have only just started with Magento and unfortuantely don't know how to do the filtering :)
Cheers guys,
Chris.
I don't know a direct way to add this condition to the collection, I'd be interested in such a solution too. But you can always check inside the loop for each product:
if (empty(Mage::getModel('catalog/product_type_configurable')->getParentIdsByChild($product->getId())))
{
echo $product->getName();
}
I've done something similar for our google feed.
This excerpt of code is what I use to check the products inheritance:
$products = Mage::getModel('catalog/product')->getCollection();
$products->addAttributeToSelect('*');
$products->addAttributeToFilter('status', 1);//enabled
$products->addAttributeToFilter('price', array('gt' => 0) );//price not 0
//$products->addAttributeToFilter('visibility', 4); //catalog, search - comment out to show all items (configurable products simple product breakdowns)
Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($products);
$prodIds=$products->getAllIds();
try {
foreach($prodIds as $productId) {
$product = Mage::getModel('catalog/product');
$product->load($productId);
// SIMPLE PRODUCTS
if($product->getTypeId() == 'simple' ) {
$prodName = trim($product->getName());
$parentIds = Mage::getModel('catalog/product_type_grouped')->getParentIdsByChild($productId);
if(!$parentIds)
$parentIds = Mage::getModel('catalog/product_type_configurable')->getParentIdsByChild($productId);
if($parentIds) {
$parentProd = Mage::getModel('catalog/product')->load($parentIds[0]);
/*
* do something if this product has a parent or do some checks against $parentProd
*/
} // end parent check
}//if SIMPLE
} // foreach
} catch(Exception $e) {
die($e->getMessage());
}
There's a function called isConfigurable in the product class.
That may be of help to you.
$product->isConfigurable();
// if its the parent object it'll be true, if its the child it'll be false.
The quickest way might be to check if the product's visibility is set to "Not Visible Individually", since simple products associated with configurable products are typically set to this. Unfortunately I don't know the precise syntax but hopefully someone else who's willing to chime in does!
Since simple products that are part of configurable products usually have a visibility value of Not Visible Individually, it probably suffices to add a visibility filter to the collection that checks for visibility of the products in the catalog:
$collection->setVisibility(Mage::getModel('catalog/product_visibility')->getVisibleInCatalogIds());
In the unlikely circumstance that the resulting products are part of a configurable product, you can use the method Mage_Catalog_Model_Product_Type_Configurable::getParentIdsByChild to check if a product is used as part of a configurable product.