如何通过字符串而不是数组实现Yii2关系? [英] How to realize Yii2 relation through string not array?

查看:44
本文介绍了如何通过字符串而不是数组实现Yii2关系?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为 ChatMessage 的类.数据库中有 2 个主要列(from_user、to_user).我想将这两列之一与用户模型 ID 相关联.我如何使用看起来像这样的关系查询

I have a class named ChatMessage. There are 2 main columns in DB (from_user, to_user). I want to relate one of these 2 columns to User model id. How can I use a relation query that looks like this

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');
}

推荐答案

简短回答:这是不可能的.

ActiveRecord 关系比你想象的要复杂,以可靠的方式支持这些条件真的很复杂/不可能.问题是关系可能在不同的上下文中使用:

ActiveRecord relations are more complicated than you may think and supporting such conditions in reliable way is really complicated/impossible. The problem is that relation may be used in different contexts:

  1. 加入:select * from chat_messages join users on users.id = chat_messages.from_user.
  2. 延迟加载:select * from users where users.id = 1.
  3. 快速加载:select * from users where users.id IN (1, 2, 3, 4).
  1. Join: select * from chat_messages join users on users.id = chat_messages.from_user.
  2. Lazy loading: select * from users where users.id = 1.
  3. Eager loading: select * from users where users.id IN (1, 2, 3, 4).

如您所见,很难将 on 条件转换为适合这三种类型的查询中的每一种 (在 GitHub 上查看此问题).

As you may see it is hard to convert your on condition to fit each of this three types of queries (see this issue at GitHub).

您可以尝试覆盖 ActiveQuery 以支持您的条件,但使用两个关系并创建一些帮助程序来更方便地访问这些关系更容易(并且可能足够好):

You may try to override ActiveQuery to support your condition, but much easier (and probably good enough) is to use two relations and create some helpers to make accessing these relations more convenient:

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();

对于简单的情况应该足够了.对于更复杂的场景,您需要手动编写查询.

It should be enough for simple cases. For more complex scenarios you will need to write queries manually.

请注意,在模型中使用 Yii::$app->user->id 被认为是不好的做法:

Note that using Yii::$app->user->id in your model is considered as bad practice:

总而言之,模型/.../

In summary, models /.../

  • 不应直接访问请求、会话或任何其他环境数据.这些数据应该由控制器注入模型;

https://www.yiiframework.com/doc/guide/2.0/en/structure-models#best-practices

这篇关于如何通过字符串而不是数组实现Yii2关系?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆