Monday, May 4, 2020

Yii CActiveRecord Relation to a Relation that is a View

I have tables for Council, Unit, Offices, CouncilOffices, and ViewWithPhonebook. The view is the records for the unit with additional data retrieved from an online phonebook.

CouncilOffices implements a many-to-many relationship between Offices and Council. The council are unit members who hold offices in the organization.

Council Relations

array(
'officeRelation'=>array(self::MANY_MANY, 'Offices', 
                              'council_offices(council_index, offices_index)'
), 
'viewRelation'=>array(self::BELONGS_TO,
            'ViewPhonebook', 'id'),

'unitRelation'=>array(self::BELONGS_TO, 
            'Unit', 'id'),       
);

CouncilOffices Relations

array(
    'councilRelation'=>array(self::BELONGS_TO, 
                             'Council', 'council_index'),
    'officesRelation'=>array(self::BELONGS_TO, 
                             'Offices', 'offices_index'),
);

Offices Relations

array(
     'councilRelation'=>array(self::MANY_MANY, 'Council',
          'council_offices(offices_index, council_index)',
      ),
);

Unit Relations

array(
     'unitRelation'=> array(self::HAS_MANY, 'Council', 'id'),);

ViewWithPhonebook Relations

return array(
     'viewRelation'=> array(self::HAS_MANY, 'Council', 'id'),);

The code worked if I used the unit relation. The problem I had was with the view, since it did not have a primary key. If I tried to include the relation, I received this SQL error.
ON
(`councilRelation`.`id`=`unitRelation`.``) WHERE (year=:year).
It is clear that the generated SQL was looking for a primary key, but couldn't find it. I searched for a long time for a solution. I finally found the solution at http://codeinch.com/yii-set-primary-key-in-model/. Add a primaryKey method to the model and return the name of the primary key.

public function primaryKey() {
    return 'ID';
}

Once this was set, I could retrieve the Council relation from Council Offices and then retrieve the View relation from the Council.

$criteria = new CDbCriteria;
$criteria->condition = 'year=:year';
$criteria->params = array(':year'=>'2020');

$data = CouncilOffices::model()
  ->with(array(
    'councilRelation'
       =>array('select'=>'index, year, id'),        
    'councilRelation.unitRelation'
       =>array('select'=>'ID, Name')))
  ->findAll($criteria);

No comments:

Post a Comment

Followers