Active Query and relations

Hello. In FavouritePostController I have:


$favourites = FavouritePost::find()->getPosts()->all();

and in FavouritePostQuery:


public function getPosts() {

        return $this->hasMany(Post::className(), ['post_id' => 'id']);

}

I was getting Calling unknown method: common\models\FavouritePostQuery::hasMany(), so I tried moving relation to AR model file, but the result was Calling unknown method: common\models\FavouritePostQuery::getPosts(). What is wrong?

Your way of using relations is wrong.

You should place getPosts method to model class.

You should use getPosts for FavouritePost instance (not for ActiveQuery instance).

Declaring relations: http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#declaring-relations

Accessing relational data: http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#accessing-relational-data

I placed getPosts in model class, but the problem is, find() is returning return ActiveQuery instance, not base Active Record. So I still have error Calling unknown method: common\models\FavouritePostQuery::getPosts()

Yes. It’s because you must use getPosts() for your ActiveRecord instance. You can’t use it for ActiveQuery. See docs I gave you above, please.

I deleted Active Query, but still does not work: Calling unknown method: yii\db\ActiveQuery::getPosts(). In docs there is example with findOne() and it is working, but what about fetching more models? I think it is not implemented yet.

As @rugabarbo suggests, you seem to have a basic misunderstanding regarding the concept of the relation in ActiveRecord.

What are your models and the tables behind them?

I guess there is Post model representing post table, and, here I’m lost. What is the related model and its backing table? FavoritePost model and favorite_post table?

And what relations have you established between them?

Table structure:

I just want get all favourited posts of user.

I still don’t understand.

What "user.favourite_post_id", "user.post_id" and "post.favourite_post_id" refer to?

IMO, these 3 columns are not necessary for you to manage the relationships among 3 tables.




user

  id ... PK

  username


post

  id ... PK

  user_id ... FK to user.id (the user that wrote this post)

  text


favorite_post

  id ... PK (not necessary, you may omit it)

  post_id ... FK to post.id

  user_id ... FK to user.id

  // the user(user_id) has favored the post(post_id)



Then, the relations should be:




/* User.php */


/* A User has many Posts that he wrote */

public function getPosts()

{

    return $this->hasMany(Post::className(), ['user_id' => 'id']);

}


/* A User has many favourite_post records */

public function getFavouritePosts()

{

    return $this->hasMany(FavouritePost::className(), ['user_id' => 'id']);

}


/* A User has many Posts that he has favored through FaouritePosts */

public function getFavPosts()

{

    return $this->hasMany(Post::className(), ['id' => 'post_id'])

        ->via('favouritePosts');

    /* Or, you may write like this */

    /*

    return $this->hasMany(Post::className(), ['id' => 'post_id'])

        ->viaTable('favourite_post', ['user_id' => 'id']);

    */

}


/* Post.php */


/* A Post has one User that wrote it */

public function getUser()

{

    return $this->hasOne(User::className(), ['id' => 'user_id']);

}


/* A Post has many favourite_post records */

public function getFavouritePosts()

{

    return $this->hasMany(FavouritePost::className(), ['post_id' => 'id']);

}


/* A Post has many Users that favored it through FaouritePosts */

public function getFavUsers()

{

    return $this->hasMany(User::className(), ['id' => 'user_id'])

        ->via('favouritePosts');

    /* Or, you may write like this */

    /*

    return $this->hasMany(User::className(), ['id' => 'user_id'])

        ->viaTable('favourite_post', ['post_id' => 'id']);

    */

}


/* FavouritePost.php */


/* A FavouritePost has one User */

public function getUser()

{

    return $this->hasOne(User::className(), ['id' => 'user_id']);

}


/* A FavouritePost has one Post */

public function getPost()

{

    return $this->hasOne(Post::className(), ['id' => 'post_id']);

}