Search code examples
yii2yii2-modelyii2-active-records

Yii2 relationship hasOne


I have 2 simple models:

class Page extends ActiveRecord {

    public static function tableName() {
        return 'page';
    }

    public function getPageType() {
        return $this->hasOne(PageType::className(), ['id', 'page_type_id']);
    }
}

class PageType extends ActiveRecord {

    public static function tableName() {
        return 'page_type';
    }

    public function getPages() {
        return $this->hasMany(Page::className(), ['page_type_id', 'id']);
    }

}

I am trying to get a list of pages and filter them by page_type_id, so i am doing:

Page::find()
     ->joinWith('pageType')
     ->where(['page.service_id' => $this->serviceId, 'page.active' => 1])
     ->all();

But I am getting the following error:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'page_type.0' in 'on clause'
The SQL being executed was: SELECT `page`.* FROM `page` 
LEFT JOIN `page_type` 
   ON 
     `page`.`id` = `page_type`.`0` 
      AND 
     `page`.`page_type_id` = `page_type`.`1` 
WHERE 
      (`page`.`service_id`=1) AND (`page`.`active`=1)

Any ideas?


Solution

  • You need to provide the column names in the relation as name=>value pairs, not comma-separated list.

    return $this->hasOne(PageType::className(), ['id', 'page_type_id']);
    

    and

    return $this->hasMany(Page::className(), ['page_type_id', 'id']);
    

    Change your relations and your classes code look like following

    class Page extends ActiveRecord {
    
        public static function tableName() {
            return 'page';
        }
    
        public function getPageType() {
            return $this->hasOne(PageType::className(), ['id'=> 'page_type_id']);
        }
    }
    
    class PageType extends ActiveRecord {
    
        public static function tableName() {
            return 'page_type';
        }
    
        public function getPages() {
            return $this->hasMany(Page::className(), ['page_type_id'=>'id']);
        }
    
    }