Yii, CGridView: filtering and sorting count column from related tables

241 views Asked by At

I have 3 tables: productions, chunks (production may have a lot of chunks, so chunks contains production_id column) and chunk_designers (chunk may have a lot of designers, so chunk_designers has a column chunk_id).

I have to render data from productions in CGridView and add a column: count of chunks (for every production item in table), which are not assigned to any chunk. In other words:

SELECT COUNT(*) FROM `chunks` 
left JOIN `chunk_designers`
ON chunks.id = chunk_designers.chunk_id
WHERE production_id = 520 AND chunk_id IS null

...where 520 - dynamic value for every row, productions.id.

ChunkController action:

function actionProductionList() {

    $model = new Productions('search');
    $model->unsetAttributes();  // clear any default values

    $dataProvider = $model->search($_GET);
    $dataProvider->criteria->order = 'start_time DESC';

    $this->render('production_list', array(
        'provider' => $dataProvider,
        'model' => $model,
    ));
}

Model Productions:

class Productions extends AppModel {
    ....
    public $unassignedBlocksCount;
    ....

    public function rules() {
        return array(
            array('unassignedBlocksCount, id, ...', 'safe'),
            array('unassignedBlocksCount, id, ...', 'safe', 'on'=>'search'),
        );
    }

    //in search() I added:
    $criteria->compare('unassignedBlocksCount', $this->unassignedBlocksCount, true);

}

And in view:

$this->widget('zii.widgets.grid.CGridView', array(
    'id' => 'menu-grid',
    'dataProvider' => $provider,
    'filter' => $model,
    'enablePagination' => true,
    'columns' => array(
        array(
            'name' => 'unassignedBlocksCount',
            'value' => 'Chunks::getUnassignedBlocksCount($data->id)'
        ),
        ...

Column data is rendered fine, but when I try to filter it, I get the following error: unknown column unassignedBlocksCount in where clause.

I tried to write in search() method in Productions model:

// subquery to retrieve the count of posts
$count_sql = "(SELECT COUNT(*) FROM `chunks` "
                 . "LEFT JOIN `chunk_designers` "
                 . "ON chunks.id = chunk_designers.chunk_id "
                 . "WHERE production_id = 520 AND chunk_id IS NULL)";

// select
$criteria->select = array(
                          '*',
                          $count_sql . " as unassignedBlocksCount",
                    );

And just added unassignedBlocksCount element in columns in view.

But I still get the same error, when filter, and also problem is that I don't know, how to get production_id in $count_sql dynamically, depending on every table row (that's why in every row for that column value is 1, because it's correct value for production_id = 520).

So, my question is: how to get sortable and filterable column in CGridView, which is calculated (by COUNT()) from data in other tables? Thanks in advance.

0

There are 0 answers