I have created block with function getRooms(). It should return collection of rooms. But since there are a lot of conditions in the search, I need to make joinLeft query with other table.
public function getRooms(){
$rooms = array();
$productId = $this->getRequest()->getParam('product');
$from = $this->getRequest()->getParam('from');
$to = $this->getRequest()->getParam('to');
$fromStamp = strtotime( $from );
$toStamp = strtotime( $to );
$rooms = Mage::getModel('reservation/roomtypes')->getCollection();
$newInventoryTable = $rooms->getTable('reservation/newinventory');
$datefilters = array('filter1'=>$fromStamp, 'filter2'=>$toStamp );
$dateconditions = array( 'filter1' => $cond1, 'filter2' => array('from'=>'ni.date_from','to'=>'ni.date_to') );
$datecond = "({$fromStamp} >= ni.date_from and {$fromStamp} <= ni.date_to) or ({$toStamp} >= ni.date_from and {$toStamp} <= ni.date_to) OR ni.date_from is NULL";
$rooms = $rooms
->addFieldToSelect('id')
->addFieldToSelect('room_type')
->addFieldToSelect('room_price_per_night')
->addFieldToSelect('second_night_price')
->addFieldToSelect('room_quantity')
->addFieldToFilter("main_table.entity_id", $productId )
->getSelect()
->where( $datecond )
->joinLeft( array("ni"=>$newInventoryTable), "main_table.id = ni.room_type_id", "SUM(ni.rooms_count) AS rooms_reserved" )
->group("main_table.id")
->having("((`room_quantity`-`rooms_reserved`) > 0) OR (`rooms_reserved` is NULL) ");
$rooms = $rooms->query();
$rooms = $rooms->FetchAll();
return $rooms;
}
I have created properly sql-query but FetchAll() give me Array(). Because I have gone to low-level Zend db API. I want get Varien Collection and use its magic getField() feature.
In other words, I want to stay in Magento-level. So how can I rewite leftJoin, group, having operators using Magento approach?
It’s very simple to fall under that simple trick. You’ve done everything correctly, except… you’ve assigned
Zend_Db_Selectinstance to your$roomvariable when you’ve done this:What you should have done instead – is assign filters to
$select, but operate with the$collectionitself. BTW you don’t need to reassign your collection to itself to apply filters. Here’s how you should do it:Now few words why you don’t need to
loadcollection before returning it. Magento has the lazy-load principle when operating with collections. It contains all info about the select and inner filters, but does not fetch query to DB until the very place, when it need to output data – like theforeachloop. Then methodloadis triggered and protected property_itemsis filled with objects. In this way you still will be able to add or remove filters and modify select object inBlockobject or even.phtmltemplate – which is of course not encouraged, but sometimes the fastest and easiest way to do.So you don’t need to
queryorfetchorloadcollection to insert it into foreach loop and get the desired array-like behavior (thanks to Iterator interface).