CakePHP使用JOIN查找方法

geo*_*310 44 php sql cakephp join

嗨,

我需要使用CakePHP find方法执行以下查询:

SELECT *
FROM `messages`
INNER JOIN users ON messages.from = users.id
WHERE messages.to = 4
ORDER BY messages.datetime DESC
Run Code Online (Sandbox Code Playgroud)

基本上我有:

  • messages表与Message模型
  • users表与User模型

并希望在一个查询中从两个表中检索信息.该users.id字段与messages.from字段相同,因此这是连接所在的字段.

我在我MessagesController这样做,所以它需要是这样的:

$this->Message->find();
Run Code Online (Sandbox Code Playgroud)

谢谢

Ste*_*hen 116

有两种主要方法可以做到这一点.其中一个是标准的CakePHP方式,另一个是使用自定义连接.

值得指出的是,这个建议适用于CakePHP 2.x,而不是3.x.

CakePHP方式

您将与用户模型和消息模型创建关系,并使用可包含的行为:

class User extends AppModel {
    public $actsAs = array('Containable');
    public $hasMany = array('Message');
}

class Message extends AppModel {
    public $actsAs = array('Containable');
    public $belongsTo = array('User');
}
Run Code Online (Sandbox Code Playgroud)

您需要将messages.from列更改为可以messages.user_id使蛋糕自动为您关联记录.

然后你可以从消息控制器执行此操作:

$this->Message->find('all', array(
    'contain' => array('User')
    'conditions' => array(
        'Message.to' => 4
    ),
    'order' => 'Message.datetime DESC'
));
Run Code Online (Sandbox Code Playgroud)

(其他)CakePHP方式

我建议使用第一种方法,因为它可以节省大量的时间和工作.第一种方法也是建立一种关系的基础,除了你现在需要的关系之外,它还可以用于任何其他的查找调用和条件.但是,cakePHP支持定义自己的连接的语法.它会像这样完成,来自MessagesController:

$this->Message->find('all', array(
    'joins' => array(
        array(
            'table' => 'users',
            'alias' => 'UserJoin',
            'type' => 'INNER',
            'conditions' => array(
                'UserJoin.id = Message.from'
            )
        )
    ),
    'conditions' => array(
        'Message.to' => 4
    ),
    'fields' => array('UserJoin.*', 'Message.*'),
    'order' => 'Message.datetime DESC'
));
Run Code Online (Sandbox Code Playgroud)

注意,我messages.from在此示例中保留了与当前表相同的字段名称.

使用两个关系到同一个模型

以下是如何使用两个关系到同一模型的第一个示例:

class User extends AppModel {
    public $actsAs = array('Containable');
    public $hasMany = array(
        'MessagesSent' => array(
            'className'  => 'Message',
            'foreignKey' => 'from'
         )
    );
    public $belongsTo = array(
        'MessagesReceived' => array(
            'className'  => 'Message',
            'foreignKey' => 'to'
         )
    );
}

class Message extends AppModel {
    public $actsAs = array('Containable');
    public $belongsTo = array(
        'UserFrom' => array(
            'className'  => 'User',
            'foreignKey' => 'from'
        )
    );
    public $hasMany = array(
        'UserTo' => array(
            'className'  => 'User',
            'foreignKey' => 'to'
        )
    );
}
Run Code Online (Sandbox Code Playgroud)

现在你可以这样做你的发现呼叫:

$this->Message->find('all', array(
    'contain' => array('UserFrom')
    'conditions' => array(
        'Message.to' => 4
    ),
    'order' => 'Message.datetime DESC'
));
Run Code Online (Sandbox Code Playgroud)