Every model in Magento has an “array like” collection object.
$collection = Mage::getModel('sales/order')->getCollection();
foreach($collection as $order)
{
echo $order->getIncrementId();
}
Each collection also has a convenience method to grab the first or the last item from the collection
$item = $collection->getFirstItem();
$item = $collection->getLastItem();
This week a client of mine called me frantically because their checkout page was crashing. After some quick log sweeping I discovered PHP was bailing because the memory_limit
of 256 MB
had been reached. We quickly upped the limit to 512 MB
for the saveOrder
action, and orders continued to flow through. Problem solved!
Well, almost solved. I put some basic monitoring in place, and noticed the memory use on the saveOrder
method was increasing with each order. This meant we had a few weeks before the limit of 512 MB
was reached. Not good.
After some memory profiling using xDebug, I found the following bit of custom code (from a long gone offshore shop) firing during the checkout page request.
$orderid = Mage::getModel('sales/order')->getCollection()->getLastItem()->getIncrementId();
On the surface, it seems harmless, and during testing it never triggered a single bug. However, as the number of orders in the system increased, this innocuous call ended up consuming silly amounts of memory. To fix the problem, we added a sort to the collection’s query, and limited it to a single item.
$orders = Mage::getModel('sales/order')->getCollection();
$orders->getSelect()->order('entity_id DESC')->limit('1');
$orderid = $orders->getLastItem()->getIncrementId();
This preserved the exact behavior of the previous code, but did so without each successful order costing a quarter gig of memory.
The long and the short of it: Don’t use getLastItem
with collections that will grow over time, especially in code that fires during a mission critical process.