Question

Basically, I have 3 tables.

house_table
===========
house_id


floor_table
===========
floor_id
house_id


room_table
===========
room_id
floor_id
is_occupied

A house has many floor, a floor has many rooms. A room belongs to one floor, a floor belongs to one house. The corresponding models created automatically by gii are HouseTable, FloorTable, RoomTable.

What I need is to findAll() houses that have rooms that are not occupied.

How do I do that? Something like this?

class HouseRecord extends CActiveRecord {
    public function relations() {
        return array(
            'FREE_ROOM_COUNT' => array(self::STAT ...???...),
        );
    }
}

Sure, I could do it with SQL, but it needs to be done this way, because the result of findAll() is used as a data provider in a grid.

UPDATE

Following tinybyte's advice, here's what finally worked.

public function relations() {
    return array(
        'FREE_ROOM_COUNT' => array(
            self::STAT ,
            'FloorTable',
            'house_id',
            'select' => 'COUNT(rt.floor_id)',
            'join' => 'INNER JOIN room_table rt ON t.floor_id = rt.floor_id',
            'condition' => 'rt.is_occupied = 0',
        ),
    );
}

And to be used as so:

    $criteria = new CDbCriteria;

    $criteria->with = array('FREE_ROOM_COUNT');
    $criteria->together = true;

    $provider = new CActiveDataProvider(HouseTable::model(), array(
        'criteria'=>$criteria,
        'pagination' => array(
            'pageSize' => 1,
        ),
    ));

    $this->widget('zii.widgets.CListView', array(
        'dataProvider'=>$provider,
        'itemView'=>'house',
    ));

Unfortunately it turns out one can not use these STAT relations as conditions! (Confirmed here: Using STAT relation in CActiveDataProvider criteria).

Was it helpful?

Solution

I think this should do the trick

'FREE_ROOM_COUNT' => array(
   self::STAT ,
  'Floor' ,
  'house_id' 
  'select' => 'count(rt.floor_id)' , // or count(rt.room_id)
  'join' => 'Inner join room_table rt ON Floor.floor_id = rt.floor_id' ,
),
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top