When adding the product attribute, set used_in_product_listing
, used_for_sort_by
and filterable
to true
.
You can do that with the following update script:
$installer = Mage::getResourceModel('catalog/setup', 'catalog_setup');
$installer->startSetup();
$installer->updateAttribute('catalog_product', 'product_type', 'used_in_product_listing', 1);
$installer->updateAttribute('catalog_product', 'product_type', 'used_for_sort_by', 1);
$installer->updateAttribute('catalog_product', 'product_type', 'is_filterable', 1);
$installer->endSetup();
Thats all, if if you are NOT using the flat catalog.
If you enable the flat catalog product feature, then you need to ensure that your custom source model implements the methods getFlatColums()
, getFlatIndexes()
and getFlatUpdateSelect()
.
If they are missing, your attribute won't be included in the generated flat tables, even if used_in_product_listing
is enabled.
Have a look at the class Mage_Eav_Model_Entity_Attribute_Source_Boolean
for an example. You can probably copy over the methods with minimal adjustments into your custom source model from there. Otherwise, please ask a new question.
Posting this as an answer, since comments just don't have the space.
It is not an answer for your actual question, but an answer none the less.
In my opinion you are approaching the problem the wrong way.
My question still stands. Why not use core functionality? What does you review module give that core do not have?
The sync? Easy enough to sync into magento's core review system, and I give some examples at the end of my ramblings.
One golden rule, when doing modules, is to enhance, not replace. If there is core functionality that closely matches your planned solution, extend it, don't replace it. Core is stable, use it :) You will end up writing a lot less code, and have a more stable module in the end. Don't re-invent the wheel. It is round, and it works well :)
Magento is a complex application, and adding 3rd party solutions (for existing functionality) needlessly adds to that complexity. This is true for any complex application, not just magento.
You state that you cannot use magento's core review functionality, as you need to sync with an external system, but it looks to me (from the code snippet given) that you are pulling in all the reviews, into the magento database, into a custom table. How you do this is not known, but I assume it is done via a cron/periodic sync. So in the end, you have just duplicated what core already has, since you are not displaying the reviews from the external system directly onto the page. You are saving it in magento db first. (which is the right way, your implementation is not quite right ;) )
Looking at your code, I can already see an inherit issue. You are using product SKU's (textual data) as a means to find the data that you need to display. You are also incorrectly calling this the $product_id
(which by the name of the variable, suggests a numeric value) In magento the product_id
(or entity_id
really) is the key value of the magento product, and you should not make matters confusing by calling a SKU field the product_id
field.
Your table, should in fact not even have the SKU as part of it's structure, but a foreign key value, referencing back to the main product_entity table in magento, ideally set with 'ON DELETE CASCADE'
Using the SKU in a textual match will cause you heaps of issues down the line. What do you do if your client decides to rename all their product sku's? (this can happen, and I have seen it happen multiple times)
But enough of that, and lets get back to the issue in not using core review system, and your sync issue.
How you get the data from the external system (API, direct db connect etc) is beyond the scope of this example, and should be the only code/module you should really need to write. (the connector to/from that system)
In my example I went with a cron based solution, thus the external review system reviews will be pulled in every x minutes)
The code is of the top of my head, thus can be incomplete, or have mistakes, it serves purely as an example of how to do it using core review system.
I also gather the only link between that system and your products is the SKU (hence why you used it as your custom review table lookup key field)
class MyModule_ExternalReviewSystem_Model_Cron {
public function importReviews($schedule){
$externalReviews = CODE TO CONNECT TO EXTERNAL SYSTEM,
AND PULL IN REVIEWS AS AN ARRAY/COLLECTION/DB
ROW ITERATOR HERE.
foreach ($externalReviews as $key => $review) {
$productId = $product->getIdBySku($externalReviews['sku']);
if ($productId) {
$data = array('nickname'=>$externalReviews['name'],
'detail'=>$externalReviews['review'],
'title'=>$externalReviews['subject']);
$review = Mage::getModel('review/review')->setData($data);
$review->setEntityId($review->getEntityIdByCode(Mage_Review_Model_Review::ENTITY_PRODUCT_CODE))
->setEntityPkValue($productId)
->setStatusId(Mage_Review_Model_Review::STATUS_APPROVED)
->setCustomerId(null)
->setStoreId(Mage::app()->getStore()->getId())
->setStores(array(Mage::app()->getStore()->getId()))
->save();
} else {
mage::log("Could not import {$externalReviews['sku']} - not found in local db")
}
}
}
}
Done, now your external system review is inside magento's review system, and magento core will take care of all the rest.
To sync back from core review system is really easier. All you need to do is create an observer which listens to the review model save event, and sync that data back on a save. Thus you would listen to the event review_save_after
, which gets passed the entire review object, from which you can get all the product details, the review data etc.
Using core functionality results in less code, less complexity, less errors, and way way less work for yourself. Not to mention time and money saved for your client :)
Hope this helps.
Best Answer
http://www.magentocommerce.com/knowledge-base/entry/magento-for-dev-part-7-advanced-orm-entity-attribute-value
The article is really long...
If the tables exist, you can use a collection extended from EAV collection