I am a newbie in magento and I need your help. I need to move 'out of stock' products to the end of the lists in search results. How can I do this?
I've found that module catalogsearch
is used for searching. Also I've seen there is a table cataloginventory_stock_item
and is_in_stock
field. Is this a correct flag for checking product is out of stock or not. And I think I should add also an order condition when data is getting from DB. But I can not find where(a file) this data is getting form catalogsearch_query
and catalogsearch_result
tables and where (and how) should I add an order condition. Can you give me an example?
I did it. And I would like to share my method with you. Maybe it's a very easy to do for guy who have already worked with magento, but not for newbie.
The 'CatalogSearch' module is responsible for search through product catalog. The module's path is 'DOC_ROOT/app/code/core/Mage/CatalogSearch'.
First of all, we should not edit core files (files in 'Mage' folder) and must override core classes and function. To achieve our goal (my topic question) we should edit some function in different classes, so we need to override this functions.
The are 2 kinds of search thought product catalog in Magento: Simple and Advanced (maybe more, but I don't know another) and we'll influence on these 2 types.
Step 1: We should tell Magento engine, that we would like to override some its core classes. Hence, we create own module. Go to '/app/etc/modules/' and create file 'YourCompany_YourModuleName.xml' with follow content:
<?xml version="1.0"?>
<config>
<modules>
<YourCompany_YourModuleName>
<active>true</active>
<codePool>local</codePool>
</YourCompany_YourModuleName>
</modules>
</config>
Step 2: Now we should create our module. Go to '/app/code/local/YourCompany/YourModuleName/' and create folders 'etc'. Put 'config.xml' file in this 'etc' folder, we must tell magetno which files/classes we want to override.
config.xml content:
<?xml version="1.0"?>
<config>
<modules>
<yourcompany_yourmodulename>
<version>0.1.0</version>
</yourcompany_yourmodulename>
</modules>
<global>
<models>
<catalogsearch>
<rewrite>
<layer>YourCompany_YourModuleName_Model_CatalogSearch_Layer</layer>
<advanced>YourCompany_YourModuleName_CatalogSearch_Advanced</advanced>
</rewrite>
</catalogsearch>
<catalogsearch_mysql4>
<rewrite>
<fulltext_collection>YourCompany_YourModuleName_Model_CatalogSearch_Mysql4_Fulltext_Collection</fulltext_collection>
<advanced_collection>YourCompany_YourModuleName_Model_CatalogSearch_Mysql4_Advanced_Collection</advanced_collection>
</rewrite>
</catalogsearch_mysql4>
</models>
</global>
</config>
Now You may have noticed that we override 4 function in 4 classes.
Step 3: Create 4 new files in our module with follow content:
'/app/code/local/YourCompany/YourModuleName/Model/CatalogSearch/Advanced.php'
class YourCompany_YourModuleName_Model_CatalogSearch_Advanced extends Mage_CatalogSearch_Model_Advanced
{
/**
* Retrieve advanced search product collection
*
* @return Mage_CatalogSearch_Model_Mysql4_Advanced_Collection
*/
public function getProductCollection(){
if (is_null($this->_productCollection)) {
$this->_productCollection = Mage::getResourceModel('catalogsearch/advanced_collection')
->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
->addMinimalPrice()
->addTaxPercents()
->addStoreFilter();
$this->_productCollection->getSelect()->joinLeft(
array('_inventory_table'=>'cataloginventory_stock_item'),
"_inventory_table.product_id = e.entity_id",
array('is_in_stock', 'manage_stock')
);
$this->_productCollection->addExpressionAttributeToSelect('on_top',
'(CASE WHEN (((_inventory_table.use_config_manage_stock = 1) AND (_inventory_table.is_in_stock = 1)) OR ((_inventory_table.use_config_manage_stock = 0) AND (1 - _inventory_table.manage_stock + _inventory_table.is_in_stock >= 1))) THEN 1 ELSE 0 END)',
array());
Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($this->_productCollection);
Mage::getSingleton('catalog/product_visibility')->addVisibleInSearchFilterToCollection($this->_productCollection);
}
return $this->_productCollection;
}
}
/app/code/local/YourCompany/YourModuleName/Model/CatalogSearch/Layer.php'
class YourCompany_YourModuleName_Model_CatalogSearch_Layer extends Mage_CatalogSearch_Model_Layer
{
public function prepareProductCollection($collection)
{
$collection->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
->addSearchFilter(Mage::helper('catalogsearch')->getQuery()->getQueryText())
->setStore(Mage::app()->getStore())
->addMinimalPrice()
->addFinalPrice()
->addTaxPercents()
->addStoreFilter()
->addUrlRewrite();
$collection->getSelect()->joinLeft(
array('_inventory_table'=>'cataloginventory_stock_item'),
"_inventory_table.product_id = e.entity_id",
array('is_in_stock', 'manage_stock')
);
$collection->addExpressionAttributeToSelect('on_top',
'(CASE WHEN (((_inventory_table.use_config_manage_stock = 1)
AND (_inventory_table.is_in_stock = 1)) OR ((_inventory_table.use_config_manage_stock = 0)
AND (1 - _inventory_table.manage_stock + _inventory_table.is_in_stock >= 1)))
THEN 1 ELSE 0 END)',
array());
Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($collection);
Mage::getSingleton('catalog/product_visibility')->addVisibleInSearchFilterToCollection($collection);
return $this;
}
}
/app/code/local/YourCompany/YourModuleName/Model/CatalogSearch/Mysql4/Advanced/Collection.php'
class YourCompany_YourModuleName_Model_CatalogSearch_Mysql4_Advanced_Collection extends
Mage_CatalogSearch_Model_Mysql4_Advanced_Collection
{
public function setOrder($attribute, $dir='desc')
{
$this->addAttributeToSort('on_top', 'desc');
parent::setOrder($attribute, $dir);
return $this;
}
}
'/app/code/local/YourCompany/YourModuleName/Model/CatalogSearch/Mysql4/Fulltext/Collection.php'
class YourCompany_YourModuleName_Model_CatalogSearch_Mysql4_Fulltext_Collection
extends Mage_CatalogSearch_Model_Mysql4_Fulltext_Collection
{
public function setOrder($attribute, $dir = 'desc')
{
if ($attribute == 'relevance') {
$this->getSelect()->order("on_top DESC")->order("relevance {$dir}");
}
else {
parent::setOrder('on_top', 'DESC');
parent::setOrder($attribute, $dir);
}
return $this;
}
}
That's it. How you can see we should just connect to 'cataloginventory_stock_item' table while getting searched data to detect what product is out of stock and add additional order for products.
Nothing special, but I've had a problem where and what should I do to achieve my goal.
p.s. if someone can offer the better way to do this - you are welcome. Yet I could not find a proper tutorial to do this.
This topic could help you : http://www.magentocommerce.com/boards/viewthread/31680/
HOWEVER, it's a very bad idea to modify the core files, or add your own files in the core directory. I would strongly recommend you to make your own module, overriding the existing core function (you should see loads of tutorials online). It's a small extension so not impossible to achieve.