I have three tables. Item, Manufacture and a join table for these two, ItemManufacture. Item has ID and Item Name. Manufacture has Manufacture ID and Manufacture Name. Item manufacture has Item ID and Manufacture ID.
I am using Yii's CGridView control to display all items with Item Name and Corresponding Manufacture Name for that item. I could able to succesfully display those things in the grid view using the tutorials given in http://www.yiiframework.com/wiki/385/displaying-sorting-and-filtering-hasmany-manymany-relations-in-cgridview/
I also able to add text field filter, as given in the tutorial. My problem is, I want to add a combobox filter for the manufacture name column. I tried by adding a filter like,
'filter'=>CHtml::listData(Manufacture::model()->findAll(), 'man_name', 'man_name')
But it didn't worked. But works for manufacture table, without any joins.
Then I tried,
'filter'=>CHtml::activeDropDownList(Manufacture::model(),'man_name', CHtml::listData(Manufacture::model()->findAll(), 'man_name', 'man_name'));
It will display a combobox with all names, but when I select any name, it is not filtering the output. Instead an empty gridview is displayed.
Can anybody explain what is going on and how to fix it?
PS:
When I print CHtml::listData(Manufacture::model()->findAll(), 'man_name', 'man_name') using print_r in the controller, it is showing all names of manufactures.
My ItemManufacture.php (Model) is
<?php
/**
* This is the model class for table "item_manufacture".
*
* The followings are the available columns in table 'item_manufacture':
* @property integer $id
* @property integer $item_id
* @property integer $manu_id
*
* The followings are the available model relations:
* @property Manufacture $manu
* @property Item $item
*/
class ItemManufacture extends CActiveRecord
{
public $searchManu;
public $searchItem;
/**
* @return string the associated database table name
*/
public function tableName()
{
return 'item_manufacture';
}
/**
* @return array validation rules for model attributes.
*/
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('item_id, manu_id', 'required'),
array('item_id, manu_id', 'numerical', 'integerOnly'=>true),
// The following rule is used by search().
// @todo Please remove those attributes that should not be searched.
array('id, item_id, manu_id', 'safe', 'on'=>'search'),
);
}
/**
* @return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'manu' => array(self::BELONGS_TO, 'Manufacture', 'manu_id'),
'item' => array(self::BELONGS_TO, 'Item', 'item_id'),
);
}
/**
* @return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
'id' => 'ID',
'item_id' => 'Item ID',
'manu_id' => 'Manufacture ID',
);
}
/**
* Retrieves a list of models based on the current search/filter conditions.
*
* Typical usecase:
* - Initialize the model fields with values from filter form.
* - Execute this method to get CActiveDataProvider instance which will filter
* models according to data in model fields.
* - Pass data provider to CGridView, CListView or any similar widget.
*
* @return CActiveDataProvider the data provider that can return the models
* based on the search/filter conditions.
*/
public function search()
{
// @todo Please modify the following code to remove attributes that should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('id',$this->id);
$criteria->compare('item_id',$this->item_id);
$criteria->compare('manu_id',$this->manu_id);
$criteria->with = array('item', 'manu');
$criteria->compare('manu.man_name', $this->searchManu->man_name, true);
$criteria->compare('item.item_name', $this->searchItem->item_name, true);
$criteria->together = true;
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'sort'=>array(
'attributes'=>array(
'manu.man_name'=>array(
'asc'=>'manu.man_name',
'desc'=>'manu.man_name DESC',
),
'item.item_name'=>array(
'asc'=>'item.item_name',
'desc'=>'item.item_name DESC',
),
'*',
),
),
));
}
/**
* Returns the static model of the specified AR class.
* Please note that you should have this exact method in all your CActiveRecord descendants!
* @param string $className active record class name.
* @return ItemManufacture the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function getOptions()
{
echo "This is output: '". $this->searchItem->item_name. "'";
print_r ( CHtml::activeDropDownList(Manufacture::model(),'man_name', CHtml::listData(Manufacture::model()->findAll(), 'man_name', 'man_name')));
//return CHtml::activeDropDownList(Manufacture::model(),'man_name', CHtml::listData(Manufacture::model()->findAll(), 'man_name', 'man_name'));
//return CHtml::listData(Manufacture::model()->findAll(), 'man_name', 'man_name');
return CHtml::dropDownList('Manufacture[man_name]', 'man_name', CHtml::listData(Manufacture::model()->findAll(), 'man_name', 'man_name'));
}
}
My ItemManufactureController.php is,
<?php
class ItemManufactureController extends Controller
{
/**
* @var string the default layout for the views. Defaults to '//layouts/column2', meaning
* using two-column layout. See 'protected/views/layouts/column2.php'.
*/
public $layout='//layouts/column2';
/**
* @return array action filters
*/
public function filters()
{
return array(
'accessControl', // perform access control for CRUD operations
'postOnly + delete', // we only allow deletion via POST request
);
}
/**
* Specifies the access control rules.
* This method is used by the 'accessControl' filter.
* @return array access control rules
*/
public function accessRules()
{
return array(
array('allow', // allow all users to perform 'index' and 'view' actions
'actions'=>array('index','view'),
'users'=>array('*'),
),
array('allow', // allow authenticated user to perform 'create' and 'update' actions
'actions'=>array('create','update'),
'users'=>array('@'),
),
array('allow', // allow admin user to perform 'admin' and 'delete' actions
'actions'=>array('admin','delete'),
'users'=>array('admin'),
),
array('deny', // deny all users
'users'=>array('*'),
),
);
}
/**
* Displays a particular model.
* @param integer $id the ID of the model to be displayed
*/
public function actionView($id)
{
$this->render('view',array(
'model'=>$this->loadModel($id),
));
}
/**
* Creates a new model.
* If creation is successful, the browser will be redirected to the 'view' page.
*/
public function actionCreate()
{
$model=new ItemManufacture;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if (isset($_POST['ItemManufacture'])) {
$model->attributes=$_POST['ItemManufacture'];
if ($model->save()) {
$this->redirect(array('view','id'=>$model->id));
}
}
$this->render('create',array(
'model'=>$model,
));
}
/**
* Updates a particular model.
* If update is successful, the browser will be redirected to the 'view' page.
* @param integer $id the ID of the model to be updated
*/
public function actionUpdate($id)
{
$model=$this->loadModel($id);
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if (isset($_POST['ItemManufacture'])) {
$model->attributes=$_POST['ItemManufacture'];
if ($model->save()) {
$this->redirect(array('view','id'=>$model->id));
}
}
$this->render('update',array(
'model'=>$model,
));
}
/**
* Deletes a particular model.
* If deletion is successful, the browser will be redirected to the 'admin' page.
* @param integer $id the ID of the model to be deleted
*/
public function actionDelete($id)
{
if (Yii::app()->request->isPostRequest) {
// we only allow deletion via POST request
$this->loadModel($id)->delete();
// if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser
if (!isset($_GET['ajax'])) {
$this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('admin'));
}
} else {
throw new CHttpException(400,'Invalid request. Please do not repeat this request again.');
}
}
/**
* Lists all models.
*/
public function actionIndex()
{
$manufacture = new Manufacture('search');
$manufacture->unsetAttributes();
if (isset($_GET['Manufacture'])) {
$manufacture->attributes = $_GET['Manufacture'];
}
$item = new Item('search');
$item->unsetAttributes();
if (isset($_GET['Item'])) {
$item->attributes = $_GET['Item'];
}
$dataProvider=new CActiveDataProvider('ItemManufacture');
$dataProvider->model->searchManu = $manufacture;
$dataProvider->model->searchItem = $item;
$this->render('index',array(
'dataProvider'=>$dataProvider,
));
}
/**
* Manages all models.
*/
public function actionAdmin()
{
$model=new ItemManufacture('search');
$model->unsetAttributes(); // clear any default values
if (isset($_GET['ItemManufacture'])) {
$model->attributes=$_GET['ItemManufacture'];
}
$this->render('admin',array(
'model'=>$model,
));
}
/**
* Returns the data model based on the primary key given in the GET variable.
* If the data model is not found, an HTTP exception will be raised.
* @param integer $id the ID of the model to be loaded
* @return ItemManufacture the loaded model
* @throws CHttpException
*/
public function loadModel($id)
{
$model=ItemManufacture::model()->findByPk($id);
if ($model===null) {
throw new CHttpException(404,'The requested page does not exist.');
}
return $model;
}
/**
* Performs the AJAX validation.
* @param ItemManufacture $model the model to be validated
*/
protected function performAjaxValidation($model)
{
if (isset($_POST['ajax']) && $_POST['ajax']==='item-manufacture-form') {
echo CActiveForm::validate($model);
Yii::app()->end();
}
}
}
And My View is
<?php
/* @var $this ItemManufactureController */
/* @var $dataProvider CActiveDataProvider */
?>
<?php
$this->breadcrumbs=array(
'Item Manufactures',
);
$this->menu=array(
array('label'=>'Create ItemManufacture','url'=>array('create')),
array('label'=>'Manage ItemManufacture','url'=>array('admin')),
);
?>
<h1>Item Manufactures</h1>
<?php
$this->widget('bootstrap.widgets.TbGridView', array(
'dataProvider' => $dataProvider->model->search(),
'type'=>'striped bordered condensed',
'pager'=>array(
'maxButtonCount'=>'7',
),
'filter'=>$dataProvider->model,
'pager'=>array
(
'pageSize' => 50,
),
'columns' => array
(
'id',
array
(
'name' => 'manu.man_name',
//'filter' => CHtml::activeTextField($dataProvider->model->searchManu, 'man_name'),
//'filter'=>CHtml::listData($dataProvider->model->searchManu, 'man_name', 'man_name')
//'filter'=>CHtml::listData(Manufacture::model()->findAll(), 'man_name', 'man_name')
//'filter'=>CHtml::listData(Manufacture::model()->findAll(), 'man_name', 'man_name')
//'filter'=>Manufacture::model()->manufactureNames
//'filter'=>ItemManufacture::model()->options
//'filter'=>Manufacture::model()->options
'filter'=>CHtml::listData(Manufacture::model()->findAll(), 'man_id', 'man_name')
//'filter'=>CHtml::dropDownList('Manufacture[man_name]', 'manu.man_name', array_merge (array(''=>''), CHtml::listData(Manufacture::model()->findAll(), 'man_name', 'man_name')))
//'filter'=>CHtml::activeDropDownList($dataProvider->model,'manu_id', CHtml::listData(Manufacture::model()->findAll(), 'man_name', 'man_name'))
),
array
(
'name' => 'item.item_name',
'filter' => CHtml::activeTextField($dataProvider->model->searchItem, 'item_name'),
),
array
(
'header' => 'Actions',
'class'=>'bootstrap.widgets.TbButtonColumn',
),
),
));
?>