Yii2-具有多列的hasMany关系

时间:2018-09-21 20:49:38

标签: yii yii2

我有一张桌子0.9

message_thread

我想在我的id sender_id recipient_id 模型中声明一个关系,该关系将按如下方式获取所有消息线程:

User

我尝试了以下方法:

SELECT *
FROM message_thread
WHERE sender_id = {user.id}
    OR recipent_id = {user.id}

但是它会生成一个public function getMessageThreads() { return $this->hasMany(MessageThread::className(), ['sender_id' => 'id']) ->orWhere(['recipient_id' => 'id']); } 查询。有谁知道该怎么做?

2 个答案:

答案 0 :(得分:2)

您不能以这种方式创建常规关系-Yii将无法映射相关记录以进行紧急加载,因此不支持此操作。您可以在this answer和相关的issue on GitHub中找到一些解释。

根据用例,您可以尝试两种方法来获得相似的结果:

1。两种常规关系和吸气剂可简化访问

public function getSenderThreads() {
    return $this->hasMany(MessageThread::className(), ['sender_id' => 'id']);
}

public function getRecipientThreads() {
    return $this->hasMany(MessageThread::className(), ['recipient_id' => 'id']);
}

public function getMessageThreads() {
    return array_merge($this->senderThreads, $this->recipientThreads);
}

通过这种方式,发送方和接收方线程具有两个独立的关系,因此可以将它们直接用于联接或急切加载。但是您也有getter,它将返回两个关系的结果,因此您可以通过$model->messageThreads访问所有线程。

2。伪造关系

public function getMessageThreads()
{
    $query = MessageThread::find()
        ->andWhere([
            'or',
            ['sender_id' => $this->id],
            ['recipient_id' => $this->id],
        ]);
    $query->multiple = true;

    return $query;
}

这不是真实的关系。您将无法在紧急加载或联接中使用它,但它将在一个查询中获取所有用户线程,并且仍将其用作常规活动记录关系-$model->getMessageThreads()将返回{{1 }}和ActiveQuery模型数组。


为什么$model->messageThreads不起作用

orOnCondition()andOnCondition()用于其他orOnCondition()条件,这些条件将始终使用ON附加到基本关系条件中。因此,如果您具有如下定义的关系:

AND

它将生成如下条件:

$this->hasMany(MessageThread::className(), ['sender_id' => 'id'])
    ->orOnCondition(['recipient_id' => new Expression('id')])
    ->orOnCondition(['shared' => 1]);

如您所见,sender_id = id AND (recipent_id = id OR shared = 1) 定义的条件与orOnCondition()定义的关系条件是分开的,它们总是使用hasMany()进行连接。

答案 1 :(得分:0)

对于此查询

SELECT *
FROM message_thread
WHERE sender_id = {user.id}
    OR recipent_id = {user.id}

您可以使用这些

$query = (new \yii\db\Query)->from("message_thread")
$query->orFilterWhere(['sender_id'=>$user_id])->orFilterWhere(['recipent_id '=>$user_id]);