2011-11-17 944 views
7

Los modelos son: stores y product, y se asocian por:cakePHP: ¿cómo consigo que los artículos cuenten para un modelo relacionado?

var $belongsTo = array(
    'Store' => array(
    'className' => 'Store', 
    'foreignKey' => 'store_id' 
     )) 

var $hasMany = array(
    'Product' => array(
'className' => 'Product', 
'foreignKey' => 'store_id' 
    )) 

Quiero obtener una lista de todas las tiendas y el recuento de los productos que tienen. ¿Cómo debo modificar la llamada: $this->Store->find('all', array(<..some conditions..>)) para devolver ese tipo de datos?

+1

¿Qué versión de CakePHP? –

+0

cake v1.3 ....... – yossi

Respuesta

16

Un método consiste en usar de la torta incorporada counterCache opción en su asociación. Esta es probablemente la opción más efectiva, aunque requiere agregar un campo a su tabla.

En su mesa stores, añadir un campo de INT llamada product_count

En su modelo Product añadir la opción counterCache a su asociación:

var $belongsTo = array(
    'Store' => array(
    'className' => 'Store', 
    'foreignKey' => 'store_id', 
    'counterCache' => true 
)); 

Siempre que se añaden o eliminan Product registros, se actualizará automáticamente el campo product_count del registro asociado Store, por lo que no hay necesidad de modificar sus operaciones find.

Tenga en cuenta que si elige esta ruta, deberá actualizar manualmente el campo product_count para que el valor inicial sea correcto, ya que solo se actualiza después de las operaciones de agregar/eliminar.

+2

+1 por enseñarme algo :) –

+0

¿Funciona de manera predeterminada cuando se hornea una tabla? – Dooltaz

1

Un sencillo encontrar toda obtendrá los datos que necesita:

$Stores = $this->Store->find('all'); 

La lista de los productos en una de las tiendas puede ser devuelto con el siguiente código donde '0' puede ser reemplazado con el número de la índice de la matriz de la tienda:

count($Stores[0]['Products']); //returns an integer 

Si desea que la lista de los productos en cada tienda, usted podría considerar un bucle sobre todas las tiendas de este modo:

foreach ($Stores as $Store) { 
    echo count($Store['Products']); 
} 

Supuestos que estoy haciendo:

  1. desea que el recuento de los productos en cada tienda, no cuenta general del producto.
  2. No le preocupa demasiado el rendimiento. Si tiene más de 50,000 registros más o menos, es posible que desee considerar combinar esto, pero será considerablemente más complicado.
2

Echa un vistazo find('count').

Sin embargo, esto puede no escala bien si lo que buscas para par estos datos con los datos de la tienda (ver la respuesta por therealtomrose).

Tuve problemas para usar find('count') y agrupar los datos. Desafortunadamente, este es uno de esos casos extremos en los que los marcos que escriben consultas fracasan.

3

Creo que algo así podría funcionar, pero no puedo probarlo desde aquí. El contenido de COUNT() puede necesitar ajustes para trabajar con Cake en sus consultas.

$this->Store->virtualFields = array('product_count' => 'COUNT(Product.id)'); 
$this->Store->find('all', array(
    'fields' => array('Store.id', 'Store.product_count'), 
    'group' => array('Store.id'), 
)); 
2

Después de CakePHP 2.0 también puede agregar conditions a su cuenta y multiple counters per model.

añadir cualquier campo entero a su Store entonces utilizar esto en su modelo de Product:

var $belongsTo = array(
    'Store' => array(
     'className' => 'Store', 
     'foreignKey' => 'store_id', 
     'counterCache' => array(
      'anyfield', array('Product.id >' => 0), 
      'stock' => array('Product.status' => 'stock') 
     ) 
    ) 
); 
Cuestiones relacionadas