How to use Cgridview and a dataprovider with has_many relation?


I have a problem using cgridview and a dataProvider with a has_many relation.

I have an active record "Invoice" (primary key: id_inv) and an active record "Payment" (primary key: id_pay, foreign key: idinv_pay). For an invoice can be many payments.

class Invoice {


  function relations() {

     return array('payment' => array(self::HAS_MANY, 'Payment', 'idinv_pay'))




I want to display into a cgridview all payments.

Let’s supose we have the entries:


  id_inv: 1 

  value_inv: 100


  id_pay: 1

  idinv_pay: 1

  value_pay: 30

  id_pay: 2

  idinv_pay: 1

  value_pay: 50

$criteria = new CDBCriteria;

$criteria->with = array('payment');

$criteria->together = true;

$dataSource = new CActiveDataProvider('Invoice', array(


                    'pagination'=> false,


$this->widget('zii.widgets.grid.CGridView', array(



        'ajaxUpdate' => false,








The result must be 2 rows, but in reality the widget display one result, because he transform the sql result into an Invoice object and there is only one invoice.

A solution will be to set the data provider with the payment class but I need to display all invoices even there is no payment for its. So this solution is not a real solution for me.

Can anyone help me?


First, make sure "payment" is not "Payment". Also try to set the pagination like:

$dataProvider = new CActiveDataProvider('Invoice', array(








I think you get the point. I don’t want pagination. Do you have a solution?

The idea is even if you set the pagination but you have not many payments, the pagination bar will not be visible. If your goal is to display ALL payments for the invoice on the same page, then just set some big number. First, try, maybe this is not what is affecting you.

The problem is not the number of payments displayed.

The problem is that if i have 2 payments for the same invoice the CActiveDataProvider will return a single row (the sql return 2 rows) due to the fact i have a single invoice id.

I found a solution …i used CSqlDataProvider insead of CActiveDataProvider.

In the custom sql set an unique field that unique identify each row of the result (i used concat(‘id_inv’,’-’,‘id_pay’) as uniqField) and set the property “id” of the CSqlDataProvider with the name of the unique field (in my case uniqField).

You could try this wiki as well: