如何在具有不同别名的模型中使用virtualField?

时间:2014-09-24 22:15:22

标签: php cakephp

主要问题涉及两个模型,USER和MESSAGE,它们之间存在关系,因为以下信息的作用如下:

消息可以由用户发送给其他用户..所以我必须确定谁是发送者和谁是接收者,并且通过将两个模型别名设置为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'
    )
);

到这里一切都很好..

每当我必须创建一条消息时,我有一个下拉列表,向我显示用户first_names的完整列表,但因为我需要知道每个人的last_name我已经创建了一个$ virtualField来加入它们(first_name和last_name),就像这样

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

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

Selecting the Receiver

主要问题是当我尝试访问引用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'的结果将它们连接在一起,但因为我一直没有使用Reciver和Senders ......(因为那些只是消息模型用法)它抛出了我的错误
我该怎么处理?有什么方法我可以把任何条件(如果否则)所以用户模型将不会使用

User.first_name

而是使用

Receive.first_name

反之亦然?

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

2 个答案:

答案 0 :(得分:2)

好的,你可以用两种方式做到这一点。首先,您可以在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();

答案 1 :(得分: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);
}

使用此技术,您可以使用:

  • User.fullname
  • Sender.fullname
  • Recipient.fullname