After reading Marius' answer on this post:
Product loop giving incorrect images
I am concerned about how exactly Magento's load() function works on product / other models. Marius mentions:
If you use the same variable $obj for loading products you get issues
like yours, because the objects are passed as reference.
However, the behavior I experienced when using ->load();
outside a loop was not exactly as mentioned there. I was trying to get the product final pricing within a loop.
$product = Mage::getModel('catalog/product');
foreach ($product_id_array as $product_id){
$product = $product->load($product_id);
echo $product->getName() . " - " . $product->getFinalPrice . "<br/>";
}
When declaring the model outside the loop, name would display correctly, but final pricing would not. If I put it inside the loop, it would function as intended.
What is the reasoning behind this? I understand that it can be a performance kill using load within a loop, but:
- How else are you meant to retrieve product final pricing? (Special pricing / special to-&from- dates taken into account), and
- Howcome only some variables malfunction like that? (I.E
->getFinalPrice();
and not->getName();
)
Best Answer
First of all let me give you a
load
-less solution for your problem. I will give an explanation after that.Here is how you can get the price attributes correctly.
Let's say you have the product ids you need.
You can retrieve the products via a collection.
Now you can loop through the
$collection
and you should be able to callgetFinalPrice
orgetSpecialPrice
and get a correct result.Now here is why it doesn't work in your approach.
final_price
is not a product attribute. It is calculated.But take a look at the
getFinalPrice
method.the code above means that if there is a vaue for
_data['final_price']
it is returned. Otherwise it is calculated via the price model.Now, when you execute your code:
This happens.
in the first iteration, the product with the first id is loaded, as expected.
And the
_data
will look something like this:When you call
getFinalPrice
for the same product, there is no_data['final_price']
so it's calculated via the price model and added to the data array that will look like this:So far so good.
But when you call
load
in the second iteration, because you call the same instance or the product model as for the first loop, the existing data is merged with what comes from the db.Let's say you get this from the db.
Merging the 2 arrays will result in
See how the
final_price
is already there, because it was already on the product instance.And when you call
getFinalPrice
you get the value set in the_data
.It doesn't happen for the name because you get a new name from the db that overrides the one you already had on the product instance.
Everything works as expected when you add the model instantiation in the loop because each time you call
load
the data from the db is merged with an empty array.I hope this clears your doubts.