Метод поиска CakePHP с СОЕДИНЕНИЕМ


Привет,

Мне нужно выполнить следующий запрос, используя метод CakePHP find:

SELECT *
FROM `messages`
INNER JOIN users ON messages.from = users.id
WHERE messages.to = 4
ORDER BY messages.datetime DESC

В основном у меня есть:

  • messages таблица с моделью Message
  • users таблица с User моделью

И хотите получить информацию из обеих таблиц в одном запросе. Поле users.id совпадает с полем messages.from, так что это то, на чем выполняется соединение.

Я делаю это в своем MessagesController, так что это должно быть что-то например:

$this->Message->find();

Спасибо

Author: elitalon, 2011-02-22

3 answers

Есть два основных способа, которыми вы можете это сделать. Один из них - стандартный способ 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');
}

Вам нужно изменить столбец messages.from на messages.user_id, чтобы cake мог автоматически связывать записи для ты.

Затем вы можете сделать это с помощью контроллера сообщений:

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

(другой) способ 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'
));

Обратите внимание, я оставил имя поля 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'
        )
    );
}

Теперь вы можете выполнить вызов поиска следующим образом:

$this->Message->find('all', array(
    'contain' => array('UserFrom')
    'conditions' => array(
        'Message.to' => 4
    ),
    'order' => 'Message.datetime DESC'
));
 111
Author: Stephen, 2016-05-04 16:24:01

Пример Otro, пользовательская разбивка данных на страницы для ОБЪЕДИНЕНИЯ

КОД в контроллере CakePHP 2.6 в порядке:

$this->SenasaPedidosFacturadosSds->recursive = -1;
    // Filtro
    $where = array(
        'joins' => array(
            array(
                'table' => 'usuarios',
                'alias' => 'Usuarios',
                'type' => 'INNER',
                'conditions' => array(
                    'Usuarios.usuario_id = SenasaPedidosFacturadosSds.usuarios_id'
                )
            ),
            array(
                'table' => 'senasa_pedidos',
                'alias' => 'SenasaPedidos',
                'type' => 'INNER',
                'conditions' => array(
                    'SenasaPedidos.id = SenasaPedidosFacturadosSds.senasa_pedidos_id'
                )
            ),
            array(
                'table' => 'clientes',
                'alias' => 'Clientes',
                'type' => 'INNER',
                'conditions' => array(
                    'Clientes.id_cliente = SenasaPedidos.clientes_id'
                )
            ),
        ),
        'fields'=>array(
            'SenasaPedidosFacturadosSds.*',
            'Usuarios.usuario_id',
            'Usuarios.apellido_nombre',
            'Usuarios.senasa_establecimientos_id',
            'Clientes.id_cliente',
            'Clientes.consolida_doc_sanitaria',
            'Clientes.requiere_senasa',
            'Clientes.razon_social',
            'SenasaPedidos.id',
            'SenasaPedidos.domicilio_entrega',
            'SenasaPedidos.sds',
            'SenasaPedidos.pt_ptr'
        ),
        'conditions'=>array(
            'Clientes.requiere_senasa'=>1
        ),
        'order' => 'SenasaPedidosFacturadosSds.created DESC',
        'limit'=>100
    );
    $this->paginate = $where;
    // Get datos
    $data = $this->Paginator->paginate();
    exit(debug($data));

ИЛИ Пример 2, НЕ активные условия:

$this->SenasaPedidosFacturadosSds->recursive = -1;
    // Filtro
    $where = array(
        'joins' => array(
            array(
                'table' => 'usuarios',
                'alias' => 'Usuarios',
                'type' => 'INNER',
                'conditions' => array(
                    'Usuarios.usuario_id = SenasaPedidosFacturadosSds.usuarios_id'
                )
            ),
            array(
                'table' => 'senasa_pedidos',
                'alias' => 'SenasaPedidos',
                'type' => 'INNER',
                'conditions' => array(
                    'SenasaPedidos.id = SenasaPedidosFacturadosSds.senasa_pedidos_id'
                )
            ),
            array(
                'table' => 'clientes',
                'alias' => 'Clientes',
                'type' => 'INNER',
                'conditions' => array(
                    'Clientes.id_cliente = SenasaPedidos.clientes_id',
                    'Clientes.requiere_senasa = 1'
                )
            ),
        ),
        'fields'=>array(
            'SenasaPedidosFacturadosSds.*',
            'Usuarios.usuario_id',
            'Usuarios.apellido_nombre',
            'Usuarios.senasa_establecimientos_id',
            'Clientes.id_cliente',
            'Clientes.consolida_doc_sanitaria',
            'Clientes.requiere_senasa',
            'Clientes.razon_social',
            'SenasaPedidos.id',
            'SenasaPedidos.domicilio_entrega',
            'SenasaPedidos.sds',
            'SenasaPedidos.pt_ptr'
        ),
        //'conditions'=>array(
        //    'Clientes.requiere_senasa'=>1
        //),
        'order' => 'SenasaPedidosFacturadosSds.created DESC',
        'limit'=>100
    );
    $this->paginate = $where;
    // Get datos
    $data = $this->Paginator->paginate();
    exit(debug($data));
 3
Author: Sergio, 2015-07-17 02:34:20
        $services = $this->Service->find('all', array(
            'limit' =>4,
            'fields' => array('Service.*','ServiceImage.*'),
            'joins' => array(
                array(
                        'table' => 'services_images',
                        'alias' => 'ServiceImage',
                        'type' => 'INNER',
                        'conditions' => array(
                        'ServiceImage.service_id' =>'Service.id'
                        )
                    ),
                ),
            )
        );

Это означает, что массив равен нулю.

 1
Author: Atanu Dolui, 2013-09-19 07:24:17