Метод поиска 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();
Спасибо
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'
));
Пример 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));
$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'
)
),
),
)
);
Это означает, что массив равен нулю.