【问题标题】:CakePHP display custom fields from arrayCakePHP 显示数组中的自定义字段
【发布时间】:2010-12-04 17:37:28
【问题描述】:

我知道标题并没有描述我想要达到的最佳效果,但我想不出其他任何东西。

假设我有以下数组:

[Sender] => Array
            (
                [0] => Array
                    (
                        [id] => 1
                        [username] => admin
                        [PrivateMessagesUser] => Array
                            (
                                [id] => 1
                                [private_message_id] => 1
                                [sender_id] => 1
                                [recipient_id] => 3
                                [sender_status] => 1
                                [recipient_status] => 0
                                [random_key] => 
                            )

                    )

                [1] => Array
                    (
                        [id] => 1
                        [username] => admin
                        [PrivateMessagesUser] => Array
                            (
                                [id] => 3
                                [private_message_id] => 1
                                [sender_id] => 1
                                [recipient_id] => 2
                                [sender_status] => 1
                                [recipient_status] => 0
                                [random_key] => 
                            )

                    )

            )

我正在使用 ContainableBehaviour 来切断额外的数据。 我的问题是:如何在PrivateMessagesUser 中存在的密钥之后过滤掉Senders?假设我只需要Sender,其中PrivateMessagesUser.recipient_id = 3。 我试过了

'Sender' => array( 
 'PrivateMessagesUser' => array(

 )
),

但它没有用。看来我必须以某种方式克服 [0]、[1]... 键,但我不知道该怎么做。

任何帮助将不胜感激!

编辑

这是我获取上面发布的数组的方法:

$this->paginate = array(
        'conditions' => array(
            'PrivateMessage.id' => $this->__getUserPrivateMessagesInbox()
        ),
        'contain' => array(
            'Sender' => array(
                'fields' => array('id', 'username'),
                'PrivateMessagesUser' => array(
                    'fields' => array('PrivateMessagesUser.id')
                    //'conditions' => array('PrivateMessagesUser.recipient_id' => $this->Auth->user('id'))
                )
            ),
            'Recipient' => array(
                'fields' => array('id', 'username'),
                'conditions' => array('Recipient.id' => $this->Auth->user('id'))
            )
        )
    );

如何编辑这些行以达到预期的效果?

编辑 2

我从 PrivateMessagesController 调用 paginate()。

协会:

用户模型:

var $hasAndBelongsToMany = array(
    'PrivateMessageSent' => array(
        'className' => 'PrivateMessage',
        'joinTable' => 'private_messages_users',
        'foreignKey' => 'sender_id',
        'associationForeignKey' => 'private_message_id',
        'unique' => true,
        'conditions' => '',
        'fields' => '',
        'order' => '',
        'limit' => '',
        'offset' => '',
        'finderQuery' => '',
        'deleteQuery' => '',
        'insertQuery' => ''
    ),
    'PrivateMessageReceived' => array(
        'className' => 'PrivateMessage',
        'joinTable' => 'private_messages_users',
        'foreignKey' => 'recipient_id',
        'associationForeignKey' => 'private_message_id',
        'unique' => true,
        'conditions' => '',
        'fields' => '',
        'order' => '',
        'limit' => '',
        'offset' => '',
        'finderQuery' => '',
        'deleteQuery' => '',
        'insertQuery' => ''
    )
);

PrivateMessage 模型:

var $hasAndBelongsToMany = array(
    'Sender' => array(
        'className' => 'User',
        'joinTable' => 'private_messages_users',
        'foreignKey' => 'private_message_id',
        'associationForeignKey' => 'sender_id',
        'unique' => true,
        'conditions' => '',
        'fields' => '',
        'order' => '',
        'limit' => '',
        'offset' => '',
        'finderQuery' => '',
        'deleteQuery' => '',
        'insertQuery' => ''
    ),
    'Recipient' => array(
        'className' => 'User',
        'joinTable' => 'private_messages_users',
        'foreignKey' => 'private_message_id',
        'associationForeignKey' => 'recipient_id',
        'unique' => true,
        'conditions' => '',
        'fields' => '',
        'order' => '',
        'limit' => '',
        'offset' => '',
        'finderQuery' => '',
        'deleteQuery' => '',
        'insertQuery' => ''
    ),
);

PrivateMessages 用户模型:

var $belongsTo = array(
    'PrivateMessage' => array(
        'className' => 'PrivateMessage',
        'foreignKey' => 'private_message_id',
        'conditions' => '',
        'fields' => '',
        'order' => ''
    ),
    'Sender' => array(
        'className' => 'User',
        'foreignKey' => 'sender_id',
        'conditions' => '',
        'fields' => '',
        'order' => ''
    ),
    'Recipient' => array(
        'className' => 'User',
        'foreignKey' => 'recipient_id',
        'conditions' => '',
        'fields' => '',
        'order' => ''
    )
);

数据库表如下:

  • users: id, username, ...
  • private_messages: id, subject, ...
  • private_messages_users: id, private_message_id, sender_id, recipient_id, status, ...

【问题讨论】:

  • 这没有意义:私信可以有多个发件人?多个收件人似乎很常见。除非这是某种形式的线程功能。
  • 你是对的,只有一个发件人。但我认为如果我与同一个模型有两种不同的关系是不对的。您如何建议更改这些关系以既有意义又保持功能?

标签: arrays cakephp filter


【解决方案1】:

有三种方法可以实现这一点。

查看您返回的数据数组,我猜是PrivateMessagesUser 属于Sender

1.查询 PrivateMessagesUser 模型

有时,只需查询正确的模型。您可以将条件直接应用于要应用限制的模型。

$this->Sender->PrivateMessagesUser->find('all', array(
    'conditions' => array('PrivateMessagesUser.recipient_id' => 3),
    'contain' => array('Sender')
));

2。将条件应用于相关模型

这并不总是有效,因为 CakePHP 的 SQL 生成并不总是按您希望的方式工作。但在像 hasMany 关系这样的简单情况下,您可以使用:

$this->Sender->find('all', array(
    'conditions' => array('PrivateMessagesUser.recipient_id' => 3),
    'contain' => array('PrivateMessagesUser')
));

同样,这只有在 Cake 对 Containable 参数执行 JOIN 并正确使用条件时才有效。

3。使用联接

这种方法是万无一失的,但由于它是高度可定制的,所以有点混乱。

$this->Sender->find('all', array(
    'joins' => array(
        array(
            'table' => 'private_messages_users',
            'alias' => 'PrivateMessagesUser',
            'type' => 'inner',
            'conditions' => array(
                'PrivateMessagesUser.sender_id = Sender.id',
                'PrivateMessagesUser.recipient_id' => 3
            )
        )
    )
));

我给您的最后一条建议是将此代码放入模型中。尽可能遵循“胖模型,瘦控制器”的原则。

Sender 模型中:

function fetchByRecipientId($recipientId) {
    ...
}

祝你好运!


编辑:为了使这项工作适用于分页,请遵循上述方法,但使用以下格式:

$this->paginate = array(
    'PrivateMessagesUser' => array(
        'conditions' => array('PrivateMessagesUser.recipient_id' => 3),
        'contain' => array('Sender'),
        // 'order' => ... other keys if you wish
    )
);
$this->set('senders', $this->paginate());

【讨论】:

  • 谢谢!我会尽量听从你的最后一条建议。但是,关于我的问题,您提供的方法似乎不起作用......我正在从 PrivateMessagesController 调用该 paginate() (find() 等)。我需要在其中显示用户的收件箱,因此需要将所有收到的消息与发件人一起获取。问题是在该 paginate() 内部,我不能在条件中使用 PrivateMessagesUser 模型,因为它输出“在条件条件下找不到字段”错误。对于处理这个特定问题还有什么其他建议吗?
  • 我已经编辑了答案以添加分页说明。希望对您有所帮助。
  • 不幸的是,这不起作用。更糟糕的是,它会选择所有邮件及其所有发件人和收件人......(我添加了仅选择某些私人邮件的条件)。我使用的方法获取收到的所有消息,以及正确的收件人(即当前用户)。问题是它选择了该消息的所有发件人以及 PrivateMessagesUser 关联,即使关联中的接收者 ID 不是当前用户。我的选择是“关闭”关联并仅选择具有正确接收者 ID 的发件人。
  • 问题是每个 Sender 都显示在一个数组中,有数字索引,所以我不知道如何“跳过”这个数字索引并在关联数组中走得更远。对不起,我知道我没有很清楚地解释这个问题,但我没有其他话可以说.. :(
  • 我需要以下信息:1) 您调用 paginate() 的控制器,2) 所有相关模型的架构/关系。
【解决方案2】:

您可以在 Containable 中放置条件,如下所示:

$this->Sender->find('all', array(
   'contain' => array(
      'PrivateMessagesUser' => array('conditions' => array('recipient_id' => 3))
   )
));

编辑: 尝试修改您的$this->paginate 如下:

$this->paginate = array(
        'conditions' => array(
            'PrivateMessage.id' => $this->__getUserPrivateMessagesInbox()//array of message id's
        ),
        'fields' => array('PrivateMessagesUser.id'),
        'contain' => array(
            'Sender' => array(
                'fields' => array('id', 'username'),
            ),
            'Recipient' => array(
                'fields' => array('id', 'username'),
                'conditions' => array('Recipient.id' => $this->Auth->user('id'))
            )
        )
    )

然后调用你的分页$this->paginate($this->PrivateMessage)

【讨论】:

  • 这个想法是我已经有一个 find() 查询,我想在其中获取和过滤所有相关数据。
  • 然后使用设置? Set::extract('/Sender/PrivateMessagesUser[recipient_id=3]', $originalData);
  • 我想在SQL查询前过滤掉数据,以免数据库中塞满无用的查询...
  • 嗯,你能用你的预期输出编辑你的问题吗?我还是没有得到你想要的,抱歉。
  • 我提到我想过滤匹配给定PrivateMessagesUser.recipient_idSender。我需要在一个查询中执行此操作。我还举了一个例子,说明我尝试过但没有奏效。我的信念是因为在Sender 中,我有很多记录,但我不知道如何为每个Sender“选择”数组(例如带有[0]、[1]、...的数组)。另一件我认为我没有说得很清楚的是上面显示的数组是 find() 的 result。我需要修改 find() 以输出所需的数组,而不是我上面发布的那个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-21
  • 1970-01-01
  • 2020-06-19
  • 1970-01-01
  • 1970-01-01
  • 2018-08-26
  • 1970-01-01
相关资源
最近更新 更多