简体   繁体   中英

Yii Framework: Display associated table entry through foreign key and search against it

Hello I am quite new to Yii Framework and I am following Larry Ullman's Tutorial Series. I have a Employee model and a Department Model. The Department Model has a has_many relation with Employee Model , departmentId being the foreign key in Employee Model.

In the admin view, I have a search bar followed by a list of Employee, I want to display the name of the Department instead of the departmentId, and also make the search through department name. For a try, I wrote the following code having an array corresponding to departmentId field. This one worked for the view action but is not working for the admin action .

Kindly Help.

<?php 
echo CHtml::link('Advanced Search','#',array('class'=>'search-button')); ?>
<div class="search-form" style="display:none">
<?php $this->renderPartial('_search',array(
'model'=>$model,
)); 
?>
</div><!-- search-form -->

<?php 
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'employee-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
    'id',
    array(
    'name'=>'departmentId',
    'value'=>$model->department->name,
    ),
    //'departmentId',
    'firstName',
    'lastName',
    'email',
    'ext',
    /*
    'hireDate',
    'leaveDate',
    */
    array(
        'class'=>'CButtonColumn',
    ),
),
)); ?>

Your view action is just a list view generated from a single model, I'm assuming. This code doesn't work in this case because CGridView is generating each row with data returned from the CActiveDataProvider you're specifying using $model->search() . So $model , in this case, is only the current model, and doesn't contain data generated by your query.

To get this to work, value should be a string that CGridView can evaluate as PHP code. So it should look like this 'value'=>'$data->department->name;', ( $data is the variable Yii uses to provide the current row to CDataColumn).

The best way I found for creating an extra searchable relation column in a gridview is by using the following pattern:

// the model class
class Product extends CActiveRecord {
    // create a custom field in your model class to hold your search data
    public $searchSupplierName;

    // [...]

    // make sure the custom field is safe to set in your rules
    public function rules() {
        return array(
            // [...]

            // add your custom field name to this rule
            array('id, searchSupplierName', 'safe', 'on'=>'search'), 
        );
    }

    // edit your search function 
    public function search() {
        // [...]

        // use the value of the custom attribute as a condition in your search
        $criteria->compare('supplier.name', $this->searchSupplierName,true);

        // you could use something like the following 
        // to make sure you don't fire a lazy loading query 
        // for every result that is shown on the gridview.
        if($this->searchSupplierName)
            $criteria->with = array( 'supplier' );

        // then do something like this if you want to be able to sort on the field
        return new CActiveDataProvider($this, array(
            'criteria'=>$criteria,
            'sort'=>array(
                'attributes'=>array(
                    'searchSupplierName'=>array(
                        'asc'=>'supplier.name',
                        'desc'=>'supplier.name DESC',
                    ),
                    '*', // this makes sure the rest of the field sorts keep working
                ),
            ),
        ));
    }
}
// in the template
<?php 
$this->widget('zii.widgets.grid.CGridView', array(
    // set the dataprovider to the changed search function output
    'dataProvider' => $model->search(),
    'filter' => $model, // model is an instance of Product in this case (obviously ;)

    // [...]

    'columns' => array(
        // [...]

        // this is the column we care (extra) about
        // notice I still use a custom value here (as @ethan describes in his answer)
        array(
            'name' => 'searchSupplierName',
            'value' => '$data->supplier->name',
        ),
    ),
)); 
?>  

This solution should work for (almost) any case you want. It is the best solution I can think of if you want text based filtering on the column.

But there are other options as well. For example if you just want to search on a relation_id by using a combobox to find the right value there are less complicated solutions .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM