i have a problem figuring out how to perform searches and how to sort the CGridView on calculated values.
i have an invoice model with a sum to pay. for every invoice there can be several payments which should add up to that sum in order to know if the invoice may be considered as ‘paid’.
In your CGridView are you displaying if the products is paid or not, or are you displaying the sum remaining to pay? (just trying to understand what you are trying to do so i could help you better!)
If this is display if the products is paid or not I would display a dropdown list in my CGridView containing 1=>"Paid" and 0=>"Not Paid" named paidProducts and in the criteria i would do something like
sorting can only be applied on SQL level. You must move all calculations you want to sort on to the database.
to allow sorting on virtual attribute ‘isPaid’ you have to:
add getter in your model:
public function getIsPaid() //important is to add 'get' prefix to allow the magic work <img src='http://www.yiiframework.com/forum/public/style_emoticons/default/smile.gif' class='bbc_emoticon' alt=':)' />
{
if($this->amount - $this->paymentsSum <= 0)
return TRUE;
else
return FALSE;
}
add sorting definition in your dataProvider (by default returned from search function):
return new CActiveDataProvider( 'Payment', array(
'criteria'=>$criteria,
'sort'=>array(
'attributes'=>array(
'isPaid'=>array(
'asc'=>'( t.amount - t.paymentsSum )', //where t is default alias for primary table in query
'desc'=>'( t.amount - t.paymentsSum ) DESC',
),
'*', //leave this or you won't be able to sort by default attributes
),
),
));
Above is a little bit tricky because displayed value will be get from getIsPaid getter, but Yii will sort on SQL condition, not the php value. This way results can be a little bit different but you can tune this
thank you all for your help. i finally managed to do it using softarks link.
the most of what i’ve done is identical to the wiki tutorial, so i’ll just show the code from the search() function.
// subquery to retrieve the 'paid' status
$payment_table = Payment::model()->tableName();
$paid_status_sql = "(select CASE WHEN t.amount-(select sum(amount) from $payment_table where $payment_table.invoice_id = t.id) <= 0 THEN 1 ELSE 0 END)";
// select
$criteria->select = array(
'*',
$paid_status_sql."as isPaid",
);
// where
$criteria->compare($paid_status_sql, $this->isPaid);