paginatecount - Modelo de CakePHP: COUNT(*) en Containable
pagination php (2)
Tengo una aplicación CakePHP 1.3 y realmente disfruto el comportamiento Containable para recuperar datos.
Supongamos que tengo publicaciones en relación uno a muchos con comentarios. Yo uso Containable para consultar (para paginación) una lista de todas las Publicaciones y los Comentarios que pertenecen. Pero solo estoy interesado en cuántos comentarios tiene cada publicación. No encontré ninguna forma de lograr esta consulta con contenido sin obtener todas las filas de Comentarios. Lo intenté:
$this->paginate=array(
''fields'' => ''Post.title, Post.created'',
''contain'' => array(''Comment''=>''COUNT(*) AS count''),
);
los resultados en "Modelo" Comentario "no están asociados con el mensaje de error" Recuento "del modelo.
$this->paginate=array(
''fields'' => array(''Post.title, Post.created''),
''contain'' => array(''Comment''=>array(''fields''=>''COUNT(*) AS count''),
);
no funciona, el conjunto de resultados contiene para cada publicación una matriz de Comentarios vacía, excepto la última, donde contiene el campo de conteo, pero teniendo el número de todos los comentarios no solo los que pertenecen.
Mi otra suposición fue
$this->paginate=array(
''fields'' => ''Post.title, Post.created, COUNT(Comment.id)'',
''contain'' => array(''Comment''=>array(''fields''=>''''),
);
pero esto da como resultado un error, porque hasMany relaciones se consultan de forma independiente, por lo que la tabla de respuestas no está en la consulta para las entradas de publicación. ¿Cómo puedo contar la cantidad de comentarios que tiene una publicación?
Bueno, la mejor manera de hacerlo es configurar un campo llamado comment_count
en la tabla de posts
y agregar esta clave a la matriz Comment Comment $ belongsTo Post:
''counterCache'' => true
Cada vez que ocurra algo con los comentarios, se actualizará el campo comment_count en la publicación relacionada (en realidad, se repite cada vez, en lugar de solo agregar o eliminar).
Es mejor, porque cuando recuperas datos para el usuario, es mucho más rápido y ni siquiera toca la tabla de comentarios. Como estás usando el comportamiento Containable, supongo que lo que estás buscando es velocidad y peso ligero.
Tenía la misma pregunta. La respuesta que dio PawelMysior fue excelente y condujo a la solución.
Encontré algunos detalles más en el libro de CakePHP: 3.7.4.1.1 counterCache - Caché tu conteo () . Esto fue útil, pero aún un poco vago. Por el bien de los demás, quiero brindar más detalles.
Tengo dos tablas: Publicación e Imagen. Cuando agregué una imagen a una publicación, quiero hacer un seguimiento de la cantidad de imágenes que cada publicación tenía para mostrar en la lista de índice de publicaciones, sin necesidad de ejecutar una consulta de conteo adicional en la tabla de imágenes.
CREATE TABLE posts
(
id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
user_id INTEGER UNSIGNED NOT NULL,
title VARCHAR(255),
body TEXT,
created DATETIME,
modified DATETIME,
image_count INTEGER UNSIGNED,
PRIMARY KEY (id)
) ENGINE=InnoDB;
CREATE TABLE images
(
id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
post_id INTEGER UNSIGNED NOT NULL,
filename VARCHAR(255),
created DATETIME,
modified DATETIME,
PRIMARY KEY (id)
) ENGINE=InnoDB;
Observe que el image_count
va en la tabla de posts
. No se necesita nada especial en la tabla de images
.
class Post extends AppModel
{
var $name = ''Memory'';
var $hasMany = array(
''Image'' => array(
''className'' => ''Image'',
''foreignKey'' => ''post_id'',
''dependent'' => false
)
);
}
class Image extends AppModel
{
var $name = ''Image'';
var $belongsTo = array(
''Post'' => array(
''className'' => ''Post'',
''foreignKey'' => ''post_id'',
''counterCache'' => true
)
);
}
Tenga en cuenta que counterCache
se agrega al modelo de Image
. No se necesita nada especial en el modelo de Post
.
$this->Post->Behaviors->attach(''Containable'');
$post = $this->Post->find(''all'', array(
''conditions'' => array(''user_id'' => 7),
''order'' => array(''Post.created DESC''),
''contain'' => array(
''Post'' => array(
''User'' => array(''first_name'', ''last_name'')
)
)
));
Ahora cuando hacemos un find
no hay necesidad de hacer nada especial para encontrar el recuento, ya que es automáticamente un campo en los resultados de la Post
. Observe el image_count
continuación.
Array
(
[Post] => Array
(
[0] => Array
(
[id] => 14
[user_id] => 7
[title] => Another great post
[body] => Lorem ipsum...
[created] => 2011-10-26 11:45:05
[modified] => 2011-10-26 11:45:05
[image_count] => 21
[User] => Array
(
[first_name] => John
[last_name] => Doe
)
)
)
)
Una cosa a tener en cuenta, si agrega counterCache a una estructura de base de datos existente, los recuentos en Post
serán cero hasta que se agregue otra Image
. En el punto, CakePHP hará un recuento real y actualizará el image_count
a la cantidad correcta.
Espero que esta información adicional sea útil para alguien.