yiicountparametersyii-relations

Yii how to count related models (getRelation with params)?


I have a HAS_MANY relation called "relationName",

So I can get all related models using

$model->relationName;

or using

$model->getRelated('relationName');

I can also get a subset of relatedModels, by adding params

$model->getRelated('relationName', true, array('fieldName'=>'val'));

So, I will get a subset of all related models, which fieldName = "val"

but how can I count them?

This idea looks like bad one (because it will take all models and then count them):

count($model->getRelated('relationName', true, array('fieldName'=>'val')));

I need something which will finally build query with COUNT(), and return result.

Using STAT relation is also looks like bad idea (because I already described relation in code, why should I duplicate the description of relation?)

So, is there any good solution to count related (HAS_MANY) models with dynamic params?


Solution

  • Ok, so I had such models: Product (product_id) Order (order_id, product_id) OrderProduct (order_id, product_id)

    Product model had relation

    'orders'=>array(self::HAS_MANY,'Order',array('order_id'=>'order_id'),'through'=>'orderedProducts'),

    My task was - to count each product->orders, without loading all orders models.

    As Ross suggested, I created STAT relation

    'statOrders'=>array(self::STAT,'Order',array('order_id'=>'order_id'),'through'=>'orderedProducts'),

    Eventually when I called $product->statOrders, I got an exception CStatRelation has no 'through' attribute

    enter image description here

    Which means that if I want to make it work, I have to invent another way to describe relation between products and orders.. It's even worse than duplication.

    Finally I came up with this workaround:

    $c=$product->getRelated('orders', true, аггау('select'=>'CОUNТ(огdегѕ.огdег_іd) as order_id', 'gгоuр'=>'ргоduсt_іd'));
    $count=$c[О]->order_id;
    

    • No need to describe new relation

    • It makes clean sql query:

    system.db.CDbCommand.query(SELECT COUNT(orders.order_id) as order_id, `orders`.`order_id` AS `t1_c0` FROM `orders` `orders` LEFT OUTER JOIN `orders_products` `orderedProducts` ON (`orderedProducts`.`order_id`=`orders`.`order_id`) WHERE (`orderedProducts`.`product_id`=:ypl0) GROUP BY product_id. Bound with :ypl0='458739')
    

    • You can dynamically add params: enter image description here

    • By analogy you can count amount of products in orders (sum products quantity in each order): enter image description here

    My current final solution: enter image description here