Magento - load only configurable products - php

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.

Related

Show Quantity Sold On Product Page for Configurable - Magento

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.

Magento Custom Sitemap

Magento's default sitemap generation produces an XML file that displays all products, including simple products that are associated with configurable products. I only want the configurable product not the associated simple products, can anyone help me?
In Mage/Sitemap/Model/Sitemap.php the function that generates the XML sitemap is generateXml() and the code block that generates the product urls is:
$changefreq = (string)Mage::getStoreConfig('sitemap/product/changefreq', $storeId);
$priority = (string)Mage::getStoreConfig('sitemap/product/priority', $storeId);
$collection = Mage::getResourceModel('sitemap/catalog_product')->getCollection($storeId);
foreach ($collection as $item) {
$xml = sprintf('<url><loc>%s</loc><lastmod>%s</lastmod><changefreq>%s</changefreq><priority>%.1f</priority></url>',
htmlspecialchars($baseUrl . $item->getUrl()),
$date,
$changefreq,
$priority
);
$io->streamWrite($xml);
}
unset($collection);
I tried using
Mage::getModel('catalog/product')->getCollection();
and changed this line:
htmlspecialchars($baseUrl . $item->getUrl()),
to this line to get it work
htmlspecialchars($item->getProductUrl()),
I get the correct products (without the associated ones), but the urls are like this:
http://www.domain.com/catalog/product/view/id/532/
I want the Url Rewrites, so i changed it to:
$collection = Mage::getModel('catalog/product')->getCollection($storeId)
->addUrlRewrite();
But i still get this:
http://www.domain.com/catalog/product/view/id/532/
Any ideas what's wrong?
you can try with below code.
$product_collection = Mage::getModel('catalog/product')->getCollection()->addAttributeToFilter('entity_id', 16)->addUrlRewrite();
echo $product_collection->getFirstItem()->getProductUrl();
or you can load url separately as you already have product collection than try something like this
Mage::getResourceSingleton('catalog/product')->getAttributeRawValue($productId, 'attribute_code', Mage::app()->getStore());

Magento - get product collection of all products

I need a custom product collection of all products. Currently there are no categories which contain all products of the store (as there are 8000 products we can not add them in to one extra category).
What I need is on a particular CMS page the product collection of all products is displayed.
So far I have a CMS page with the block:
{{block type="catalog/product_list" template="catalog/product/list.phtml"}}
I have created an module to override 'Mage_Catalog_Block_Product_List'
I believe the function I need to edit would be 'protected function _getProductCollection()'
As we can see in the block call theres no category specified. What I need is in the overidden _getProductCollection function is all products in the store returned.
Is there any way this can be achieved?
There are several ways you can get the list of products from a store.
Try this way :
<?php
$_productCollection = Mage::getModel('catalog/product')
->getCollection()
->addAttributeToSort('created_at', 'DESC')
->addAttributeToSelect('*')
->load();
foreach ($_productCollection as $_product){
echo $_product->getId().'</br>';
echo $_product->getName().'</br>';
echo $_product->getProductUrl().'</br>';
echo $_product->getPrice().'</br>';
}
?>
Don't override the List block, this will have an effect on the real product listing pages.
The simple way to to copy the file to the local namespace and rename it:
from:
app/code/core/Mage/Catalog/Block/Product/List.php
to:
app/code/local/Mage/Catalog/Block/Product/Fulllist.php
You can then use your new block without having to make a full module, and it will mean your List block will work the same and not break anything on your store.
You can then safely modify the as required:
/**
* Retrieve loaded category collection
*
* #return Mage_Eav_Model_Entity_Collection_Abstract
*/
protected function _getProductCollection()
{
$collection = Mage::getModel('catalog/product')->getCollection();
// this now has all products in a collection, you can add filters as needed.
//$collection
// ->addAttributeToSelect('*')
// ->addAttributeToFilter('attribute_name', array('eq' => 'value'))
// ->addAttributeToFilter('another_name', array('in' => array(1,3,4)))
//;
// Optionally filter as above..
return $collection;
}
You can then use your new block like so:
{{block type="catalog/product_fulllist" template="catalog/product/list.phtml"}}

Magento - Adding a random product to .../template/catalog/product/view.phtml

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.

Checking if a Magento product is a child of a configurable product

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.

Categories