Hola,
Necesito hacer la siguiente consulta usando el método de búsqueda de CakePHP:
SELECT * FROM `messages` INNER JOIN users ON messages.from = users.id WHERE messages.to = 4 ORDER BY messages.datetime DESC
Básicamente tengo:
messages
con un model de Message
users
con model de User
y desea recuperar información de ambas tablas en una consulta. El campo users.id
es el mismo que el campo messages.from
, de modo que en eso se encuentra la unión.
Lo estoy haciendo en mi MessagesController
así que necesitaría ser algo así como:
$this->Message->find();
Gracias
Hay dos forms principales en que puede hacer esto. Uno de ellos es el modo estándar de CakePHP, y el otro está utilizando una combinación personalizada.
Vale la pena señalar que este consejo es para CakePHP 2.x, no 3.x.
Crearía una relación con su model de Usuario y Modelo de Mensajes, y usaría el comportamiento que se puede contener:
class User extends AppModel { public $actsAs = array('Containable'); public $hasMany = array('Message'); } class Message extends AppModel { public $actsAs = array('Containable'); public $belongsTo = array('User'); }
Debe cambiar los messages.from
columna para que sea messages.user_id
para que cake pueda asociar automágicamente los loggings por usted.
Entonces puede hacer esto desde el controller de posts:
$this->Message->find('all', array( 'contain' => array('User') 'conditions' => array( 'Message.to' => 4 ), 'order' => 'Message.datetime DESC' ));
Recomiendo usar el primer método, porque le ahorrará mucho time y trabajo. El primer método también sirve de base para establecer una relación que se puede usar para cualquier cantidad de llamadas y condiciones de búsqueda además de la que necesita ahora. Sin embargo, cakePHP admite una syntax para definir tus propias uniones. Se haría así, desde 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' ));
Tenga en count que dejé el nombre del campo messages.from
mismo que su tabla actual en este ejemplo.
Aquí puede ver cómo puede hacer el primer ejemplo usando dos relaciones con el mismo model:
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' ) ); }
Ahora puedes hacer tu llamada de búsqueda de esta manera:
$this->Message->find('all', array( 'contain' => array('UserFrom') 'conditions' => array( 'Message.to' => 4 ), 'order' => 'Message.datetime DESC' ));
Otro ejemplo, pagination de datos personalizada para JOIN
CÓDIGO en el controller CakePHP 2.6 está bien:
$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));
O Ejemplo 2, NO condiciones activas:
$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' ) ), ), ) );
Goge to array es nulo.