我有一个名为ChatMessage的类。 DB中有2个主要列(from_user,to_user)。我想将这两列中的一列与User model id相关联。如何使用看起来像这样的关系查询
public function getChattedUser()
{
return $this->hasOne(User::className(), '(case when(chat_message.from_user={Yii::$app->user->id}) then chat_message.to_user else chat_message.from_user END)=user.id');
}
答案 0 :(得分:0)
简短回答:这是不可能的。
ActiveRecord关系比你想象的更复杂,以可靠的方式支持这些条件真的很复杂/不可能。问题是关系可能在不同的环境中使用:
select * from chat_messages join users on users.id = chat_messages.from_user
。select * from users where users.id = 1
。select * from users where users.id IN (1, 2, 3, 4)
。您可能会发现很难将on
条件转换为适合这三种类型的查询(see this issue at GitHub)。
您可以尝试覆盖ActiveQuery
以支持您的情况,但更容易(也可能更好)是使用两个关系并创建一些帮助以使访问这些关系更方便:
public function getUserFrom() {
return $this->hasOne(User::className(), ['id' => 'user_from']);
}
public function getUserTo() {
return $this->hasOne(User::className(), ['id' => 'user_to']);
}
public function getUser() {
return Yii::$app->user->id == $this->user_from ? $this->userFrom : $this->userTo;
}
触发急切加载:
ChatMessage::find()->with(['userFrom', 'userTo'])->all();
对于简单的案例来说应该足够了。对于更复杂的场景,您需要手动编写查询。
请注意,在模型中使用Yii::$app->user->id
被视为不良做法:
总之,型号/.../
- 不应直接访问请求,会话或任何其他环境数据。这些数据应由控制器注入 模型;
https://www.yiiframework.com/doc/guide/2.0/en/structure-models#best-practices
答案 1 :(得分:-2)
只需在关系函数中添加if语句即可实现。只需在if语句中编写case
逻辑,如下所示:
public function getChattedUser()
{
if ($this->from_user == Yii::$app->user->id) {
return $this->hasOne(User::className(), ['id' => 'to_user']);
}
return $this->hasOne(User::className(), ['id' => 'from_user']);
}