【问题标题】:How to use virtualFields in a model with different aliases?如何在具有不同别名的模型中使用 virtualFields?
【发布时间】:2014-09-24 22:15:22
【问题描述】:

主要问题涉及两个模型,用户和消息,它们有关系,因为消息的作用如下:

消息可以由用户发送给其他用户..所以我必须确定谁是发送者和谁是接收者,我通过为 USER 设置两个模型别名来做到这一点,即“发送者”和“接收者” '(像这样)。

//This is on User model
'MessageSender' => array(
        'className' => 'Message',
        'foreignKey' => 'sender_id'
    ),
    'MessageRecipient' => array(
        'className' => 'Message',
        'foreignKey' => 'recipient_id'
    ),

Messages 中的关系是这样的。

public $belongsTo = array(
    'Recipient' => array(
        'className' => 'User',
        'foreignKey' => 'recipient_id'
    ),
    'Sender' => array(
        'className' => 'User',
        'foreignKey' => 'sender_id'
    )
);

到这里一切都很好..

每当我必须创建一条消息时,我都会有一个下拉列表显示用户名的完整列表,但因为我需要知道每个人的姓氏,所以我创建了一个 $virtualField 来加入他们(名字和姓氏)像这样.

//this is located on the USER model
public $virtualFields = array(
    'fullname' =>   'CONCAT(Recipient.first_name, " ", Recipient.last_name)'
);

我如何在消息创建中使用用户?好吧,我正在使用将要发送新消息的人作为发件人,因此发件人是用户的 ID,而收件人是下拉列表中的选定用户...

主要问题是当我尝试访问引用 USER 模型的网站的任何其他部分时,它会抛出这个错误:

Database Error
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Recipient.first_name' in 'field list'

当然是因为我的 virtualField 期望来自 'Recipient.first_name' 和 'Recipient.last_name' 的结果将它们连接在一起,但是因为我没有一直使用 Recivers 和 Senders...(因为这些只是用于消息模型的使用)它给我一个错误
我应该如何处理?有什么办法我可以设置任何条件(如果其他),这样用户模型就不会使用

User.first_name

改为使用

Receive.first_name

反之亦然?

如果您需要任何其他信息,请询问,我将非常感谢,最好的问候!

【问题讨论】:

  • 您需要这个虚拟字段一次还是在项目的许多地方都使用它?
  • 是的,我只在项目的这一部分需要它..

标签: php cakephp


【解决方案1】:

好的,您可以通过两种方式做到这一点。首先,您可以在 find() 之前动态定义此虚拟字段:

$this->YourModel->virtualFields = array('fullname' => 'CONCAT(Recipient.first_name, " ", Recipient.last_name)');
$this->YourModel->find(...);

或者(如果你有更多的虚拟字段)

$this->YourModel->virtualFields['fullname'] = 'CONCAT(Recipient.first_name, " ", Recipient.last_name)';
$this->YourModel->find(...);

第二种方式,未来更灵活,你可以在beforeFind()回调中附加这个虚拟字段,基于一些开关变量。因此,在您的查找查询之前,您可以激活一个开关,这个虚拟字段将被附加到查询中。

class YourModel extends AppModel {
    private $_fullNameEnabled = false;

    public function beforeFind($queryData) {
        parent::beforeFind($queryData);

        if (!empty($this->_fullNameEnabled)) {
            $this->virtualFields = array('fullname' => 'CONCAT(Recipient.first_name, " ", Recipient.last_name)');
        }

        return $queryData;
    }

    public function fullnameFieldStatus($status = true) {
        $this->_fullNameEnabled = $status;
    }
}

然后在您致电find() 之前使用:

$this->YourModel->fullnameFieldStatus();

【讨论】:

    【解决方案2】:

    还有第三种方法:动态构造虚拟字段,同时考​​虑到您的模型被引用的别名。

    public function __construct($id = false, $table = null, $ds = null) {
        parent::__construct($id, $table, $ds);
        $this->virtualFields['fullname'] = sprintf("CONCAT(%s.first_name, ' ', %s.last_name)", 
                , $this->alias, $this->alias);
    }
    

    通过这种技术,您可以使用:

    • 用户全名
    • 发件人全名
    • 收件人全名

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多