Two related tables in CGridView search view

I have two related tables. I want to use the search function in the admin section of my application. However, I can’t figure out how to merge the two tables in one search function. I already merge them in the same CGridView but when it comes to searching, it only searches in one table and not in another one. I cannot search with two tables. My tables are HDS and Employee, where HDS is a subset of Employee.

Here’s a part of the code of admin.php of HDS:




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

	'id'=>'hds-grid',

	'dataProvider'=>$hds->search(),

	'filter'=>$hds,

	'columns'=>array(

		'employee.id',

		'employee.fname',

		'employee.lname',

		'employee.mi',

		'employee.address',

		'employee.dob',

		'active',

		'date_update',

		array(

			'class'=>'CButtonColumn',

		),

	),

)); ?>



Thanks!

Hi,

Have a look at this

http://www.yiiframework.com/forum/index.php?/topic/5304-find-by-related-table-attribute/

That didn’t help. Actually, that’s quite far from my issue.

This is the code from HdsController::actionAdmin()




public function actionAdmin()

	{

		$hds=new Hds('search');

		

		$hds->unsetAttributes();  // clear any default values

		

		if(isset($_GET['Hds'], $_GET['Employee']))

			$hds->attributes=$_GET['Hds'];

		

		$this->render('admin',array(

			'hds'=>$hds,

		));

	}



admin.php




<?php $this->renderPartial('_search',array(

	'hds'=>$hds,

)); ?>

</div><!-- search-form -->


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

	'id'=>'hds-grid',

	'dataProvider'=>$hds,

	'filter'=>$hds,

	'columns'=>array(

		'employee.id',

		'employee.fname',

		'employee.lname',

		'employee.mi',

		'employee.address',

		'employee.dob',

		'active',

		'date_update',

		array(

			'class'=>'CButtonColumn',

		),

	),

)); ?>



_search.php




<div class="row">

		<?php echo $form->label($hds,'id'); ?>

		<?php echo $form->textField($hds,'id'); ?>

	</div>

	

	<div class="row">

		<?php echo $form->label($hds,'fname'); ?>

		<?php echo $form->textField($hds,'fname',array('size'=>45,'maxlength'=>45)); ?>

	</div>


	<div class="row">

		<?php echo $form->label($hds,'lname'); ?>

		<?php echo $form->textField($hds,'lname',array('size'=>45,'maxlength'=>45)); ?>

	</div>

...



Whenever I click the Manage HDS, there’s an error. “Property “Hds.fname” is not defined.” How would I resolve that? I’m thinking to modify the Hds::search() and add the “with” parameter. However, I don’t know how to do that.

Thanks!

Hi Tony_gen,

can you filter the result from two related tables using CGridView?

I can’t. I already tried this.




'dataProvider'=>$hds->employee->search(),

'filter'=>$hds->employee,



No luck.

What are the relations that you are using?

Actually, you should first study http://www.yiiframework.com/doc/api/1.1/CDbCriteria and check there How to set the related object there and then append the code in your HDS model’s search function.

Here is the process

1 - create a public variable say $keyword

2 - assign it to search function in rules as safe

3 - In search function, call the related data using with keyword


        $criteria = new CDbCriteria;

        $criteria->with = array('relation name');

4 - Then you need to set the data for compare as




      $criteria->compare('relation.field', $this->keyword, true);



5 - If you want to sort it too, then create a new object of CSort and set it there as




$sort = new CSort();

	$sort->attributes = array(

			'keyword'=>array(

				'asc'=>'relation.field',

				'desc'=>'relation.field desc',

			),

);



Hope this will help you.

same situation… haiz.

about the search view. Need change the function search to search the 2 related tables.


$criteria->compare('username', $this->id, true);

need compare with 2 related table. i still in progress to compare the 2 related table. But no luck till now. tell you when find out.


public function search()

        {

                // Warning: Please modify the following code to remove attributes that

                // should not be searched.

                //$model=$this->loadModel();


                $criteria=new CDbCriteria;


                $criteria->compare('username', $this->id, true);

                $criteria->compare('email', $this->email, true);

                $criteria->compare('createtime', $this->createtime, true);


                return new CActiveDataProvider('get_class($this)', array(

                        'criteria'=>$criteria,

                ));

        }

This is one of the relations:

Hds::relations()




'employee' => array(self::BELONGS_TO, 'Employee', 'employee_id'),



I’m now trying your solution.

It seems like the


$criteria->with = array('relation name');

doesn’t work because the data that are shown in the CGridView are not filtered with the relation. Really need help.

Any ideas/suggestions?

btw…how do I properly use the "with" keyword?

What error you got? or what is the code used for getting the results?

There is no error display but the thing is the adminHds displays all employee (both Hds and Staff) but should only display Hds. I have this code in my to admin views: adminHds and adminStaff because Hds and Staff are subclass of Employee.




...

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

	'id'=>'employee-grid',

	'dataProvider'=>$employee->searchHds(),

	'filter'=>$employee,

	'columns'=>array(

		'id',

		'fname',

		'lname',

		'minitial',

		'address',

		'tinId',

....



The search in CGridView does not function too.

can u share the code for searchHds and action code?

If you can share the model code then it will help to get insight of the problem

Sorry for the late reply. Here is my code:




<?php


/**

 * This is the model class for table "employee".

 *

 * The followings are the available columns in table 'employee':

 * @property integer $id

 * @property string $fname

 * @property string $lname

 * @property string $minitial

 * @property string $address

 * @property string $dob

 * @property string $mobile

 * @property string $landline

 * @property string $email

 * @property string $gender

 * @property string $civilStatus

 * @property string $religion

 * @property string $marriageDate

 * @property string $dateHired

 * @property string $sssId

 * @property string $tinId

 *

 * The followings are the available model relations:

 * @property Attachment[] $attachments

 * @property Dependent[] $dependents

 * @property EmpBenefit[] $empBenefits

 * @property Hds[] $hds

 * @property HubEmployee[] $hubEmployees

 * @property PayHeader[] $payHeaders

 * @property Staff[] $staffs

 */

class Employee extends CActiveRecord

{	

	public $active, $dateUpdate;

	public $jobtitle, $date_positioned, $rate;

	

	const GENDER_MALE='Male';

    const GENDER_FEMALE='Female';

    const CIVIL_SINGLE='Single';

    const CIVIL_MARRIED='Married';

    const CIVIL_WIDOWED='Widowed';

    const CIVIL_SEPARATED='Separated';

        

    public function getGenderOptions()

    {

        return array(

             self::GENDER_MALE=>'Male',

             self::GENDER_FEMALE=>'Female',

         );

     }

     

     public function getCivilOptions()

     {

     	return array(

	     	self::CIVIL_SINGLE=>'Single',

	     	self::CIVIL_MARRIED=>'Married',

     		self::CIVIL_WIDOWED=>'Widowed',

     		self::CIVIL_SEPARATED=>'Separated',

     	);

     }

	

	/**

	 * Returns the static model of the specified AR class.

	 * @return Employee the static model class

	 */

	public static function model($className=__CLASS__)

	{

		return parent::model($className);

	}


	/**

	 * @return string the associated database table name

	 */

	public function tableName()

	{

		return 'employee';

	}


	/**

	 * @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('fname, lname, minitial, address, dob, mobile, landline, email, gender, civilStatus, religion, dateHired, sssId, tinId', 'required'),

			array('fname, lname, email, religion, sssId, tinId', 'length', 'max'=>45),

			array('email', 'email'),

			array('minitial', 'length', 'max'=>2),

			array('address', 'length', 'max'=>100),

			array('mobile', 'length', 'max'=>20),

			array('landline, civilStatus', 'length', 'max'=>15),

			array('gender', 'length', 'max'=>6),

			array('marriageDate', 'safe'),

			// The following rule is used by search().

			// Please remove those attributes that should not be searched.

			array('id, fname, lname, minitial, address, dob, mobile, landline, email, gender, civilStatus, religion, marriageDate, dateHired, sssId, tinId', '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(

			'attachments' => array(self::HAS_MANY, 'Attachment', 'employee_id'),

			'dependents' => array(self::HAS_MANY, 'Dependent', 'employee_id'),

			'empBenefits' => array(self::HAS_MANY, 'EmpBenefit', 'employee_id'),

			'hds' => array(self::HAS_MANY, 'Hds', 'employee_id'),

			'hubEmployees' => array(self::HAS_MANY, 'HubEmployee', 'employee_id'),

			'payHeaders' => array(self::HAS_MANY, 'PayHeader', 'employee_id'),

			'staffs' => array(self::HAS_MANY, 'Staff', 'employee_id'),

		);

	}


	/**

	 * @return array customized attribute labels (name=>label)

	 */

	public function attributeLabels()

	{

		return array(

			'id' => 'ID',

			'fname' => 'First Name',

			'lname' => 'Last Name',

			'minitial' => 'Middle Initial',

			'address' => 'Address',

			'dob' => 'Date of Birth',

			'mobile' => 'Mobile',

			'landline' => 'Landline',

			'email' => 'Email',

			'gender' => 'Gender',

			'civilStatus' => 'Civil Status',

			'religion' => 'Religion',

			'marriageDate' => 'Marriage Date',

			'dateHired' => 'Date Hired',

			'sssId' => 'SSS',

			'tinId' => 'TIN',

			'staffposition' => 'Staff Position',

		);

	}


	/**

	 * Retrieves a list of models based on the current search/filter conditions.

	 * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.

	 */

	public function searchHds()

	{

		// Warning: Please modify the following code to remove attributes that

		// should not be searched.


		$criteria=new CDbCriteria;

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

		$criteria->compare('id',$this->id);

		$criteria->compare('fname',$this->fname,true);

		$criteria->compare('lname',$this->lname,true);

		$criteria->compare('minitial',$this->minitial,true);

		$criteria->compare('address',$this->address,true);

		$criteria->compare('dob',$this->dob,true);

		$criteria->compare('mobile',$this->mobile,true);

		$criteria->compare('landline',$this->landline,true);

		$criteria->compare('email',$this->email,true);

		$criteria->compare('gender',$this->gender,true);

		$criteria->compare('civilStatus',$this->civilStatus,true);

		$criteria->compare('religion',$this->religion,true);

		$criteria->compare('marriageDate',$this->marriageDate,true);

		$criteria->compare('dateHired',$this->dateHired,true);

		$criteria->compare('sssId',$this->sssId,true);

		$criteria->compare('tinId',$this->tinId,true);

		$criteria->compare('hds.active',$this->active,true);

		$criteria->compare('hds.dateUpdate',$this->dateUpdate,true);

		return new CActiveDataProvider($this, array(

			'criteria'=>$criteria,

		));

	}

	

	public function searchStaff()

	{

		// Warning: Please modify the following code to remove attributes that

		// should not be searched.

	

		$criteria=new CDbCriteria;

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

		$criteria->compare('id',$this->id);

		$criteria->compare('fname',$this->fname,true);

		$criteria->compare('lname',$this->lname,true);

		$criteria->compare('minitial',$this->minitial,true);

		$criteria->compare('address',$this->address,true);

		$criteria->compare('dob',$this->dob,true);

		$criteria->compare('mobile',$this->mobile,true);

		$criteria->compare('landline',$this->landline,true);

		$criteria->compare('email',$this->email,true);

		$criteria->compare('gender',$this->gender,true);

		$criteria->compare('civilStatus',$this->civilStatus,true);

		$criteria->compare('religion',$this->religion,true);

		$criteria->compare('marriageDate',$this->marriageDate,true);

		$criteria->compare('dateHired',$this->dateHired,true);

		$criteria->compare('sssId',$this->sssId,true);

		$criteria->compare('tinId',$this->tinId,true);

		$criteria->compare('staffs.jobtitle',$this->jobtitle,true);

		$criteria->compare('staffs.date_positioned',$this->date_positioned,true);

		$criteria->compare('staffs.rate',$this->rate,true);

		return new CActiveDataProvider($this, array(

				'criteria'=>$criteria,

		));

	}

}


//Employee Controller

....

	public function actionAdmin()

	{

		$type = $_GET['type'];

		if ($type == 'Hds'){

			$admin = 'adminHds';

			$employee = new Employee('searchHds');

			$typeModel = new Hds('search');

		}

			

		else if ($type == 'Staff'){

			$admin = 'adminStaff';

			$employee = new Employee('searchStaff');

			$typeModel = new Staff('search');

		}

		$employee->unsetAttributes();  // clear any default values

		$typeModel->unsetAttributes(); 

		if(isset($_GET['Employee']))

			$employee->attributes=$_GET['Employee'];

		

		$this->render($admin,array(

			'employee'=>$employee,

			'type'=>$type,

			'typeModel'=>$typeModel

		));

	}

...



All seems to be correct except

set




         $active, $dateUpdate;

         $jobtitle, $date_positioned, $rate;




to search safe

here




 array('id, fname, lname, minitial, address, dob, mobile, landline, email, gender, civilStatus, religion, marriageDate, dateHired, sssId, tinId', 'safe', 'on'=>'search'),

                );




I already did that but it’s still not functioning. These are my problems:

  1. the records shown in the CGridView are not properly filtered because:

        -if I manage Staff only those records who are in both employee and staff table must be shown
    
    
        -if I manage Hds only those records who are in both employee and hds table must be shown
    

Can I just simply use this condition without doing the ‘with’ keyword?:




t.id NOT IN (SELECT employee_id FROM employee, hds WHERE employee.id = employee_id); //forHds

't.id NOT IN (SELECT employee_id FROM employee, staff WHERE employee.id = employee_id)'; //forStaff



  1. searching with all the Employee’s model attributes is fine except for id(PK of Employee table/model)

  2. searching with the Hds’ or Staff’s model attributes is still not functioning

There seems to be no more issue with the code.