Método de búsqueda de CakePHP con JOIN

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:

  • tabla de messages con un model de Message
  • tabla de 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.

El path de CakePHP

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' )); 

La (otra) forma de CakePHP

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.

Usando dos relaciones con el mismo model

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.