CGridView Filter Multiple Models - php

I have searched and searched for an answer to my problem but neither of them worked. My problem is regarding the filtering/searching in the CGridView for Yii.
In my Applicant model I have the following:
private $_city = null;
private $province_id = null;
public function getCity()
{
if($this->_city === null && $this->address_id !== null) {
$this->_city = $this->address->city;
}
return $this->_city;
}
public function setCity($value)
{
$this->_city = $value;
}
public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->with = array('address'=>array('alias'=>'address'));
$criteria->compare('id',$this->id);
$criteria->compare('phn',$this->phn);
$criteria->compare('gender',$this->gender);
$criteria->compare('dob',$this->dob,true);
$criteria->compare('first_name',$this->first_name,true);
$criteria->compare('last_name',$this->last_name,true);
$criteria->compare('band_id',$this->band_id);
$criteria->compare('note',$this->note,true);
$criteria->compare('address.city',$this->city);
$criteria->compare('address.province_id',$this->province_id);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'sort'=>array(
'attributes'=>array(
'id',
'phn',
'first_name',
'last_name',
'band_id',
'city'=>array(
'asc'=>'address.city ASC',
'desc'=>'address.city DESC',
),
'province_id'=>array(
'asc'=>'address.province_id ASC',
'desc'=>'address.province_id DESC',
),
)
)
));
}
In my View I have
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'applicants-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'first_name',
'last_name',
'phn',
array(
'name'=>'band_id',
'value'=>'$data->band->name',
'filter'=>CHtml::listData(Band::model()->findAll(), 'id', 'name')
),
array(
'name'=>'city',
'value'=>'$data->address->city', // causes 'Trying to get property of non-object' - no error if $data->city
'filter'=>CHtml::listData(Address::model()->findAll(), 'city', 'city'),
),
array(
'class'=>'CButtonColumn',
'template'=>'{view}',
'buttons'=>array(
'view'=>array(
'url'=>'Yii::app()->createUrl("/applicant/view", array("id"=>$data->id))',
)
)
),
)
));
I have the cities and drop down list showing but when I choose are city from the dropdown it does not filter the widget with the proper results.
I have tried doing the solutions in the following pages
http://www.yiiframework.com/forum/index.php?/topic/11546-cgridview-with-mulitple-model/
http://www.yiiframework.com/forum/index.php?/topic/19913-cgridview-with-multiple-models/

Are you searching on the primary key of the city table in your compare statement?
E.g., if the PK of city is "city_id" you would need to change the lines below in your model and view, respectively:
$criteria->compare('address.city_id',$this->city);
'filter'=>CHtml::listData(Address::model()->findAll(), 'city_id', 'city')
(In this example you would leave "city" as the name so it displays as text in the grid, but specify the PK, city_id, in the listData in the value attribute.)

Related

Cgridview In Parentview

Yii 1.1.14
I have an employee table and a comment table
In the employee view i want to show all the comments of the employee in a grid (after the employee fields)
I tried to follow the example here
Here is where I am :
New code to defining a new search function in the model :
public $commentdate_param;
public $commentobservation_param;
...
public function rules()
{
return array(
...
array('public $commentdate_param, commentobservation_param, ...', 'safe', 'on'=>'search, searchIncludingComments'),
);
public function relations()
{
return array(
...
'employeecomments' => array(self::HAS_MANY, 'Employeecomments', 'employee_id'),
);
}
public function searchIncludingComments($parentID)
{
$criteria=new CDbCriteria;
$criteria->with=array('employeecomments');
$criteria->together = true;
$criteria->compare('t.employee_id',$parentID,false);
$criteria->compare('employeecomments.date', $this->commentdate_param,true);
$criteria->compare('employeecomments.observation', $this->commentobservation_param,true);
$sort = new CSort;
$sort->attributes = array(
'commentdate_param' => array(
'asc' => 'date_desc',
'desc' => 'date_desc DESC',
), '*', /* Treat all other columns normally */
);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'sort'=>$sort,
));
}
Adding code in the controller actionView :
...
$child_model = new Employee("searchIncludingComments");
$child_model->unsetAttributes();
$this->render('view',array(
'model'=>$this->loadModel($id),
'child_model'=>$child_model,
'parentID' => $id
));
Adding code in the view :
...
<h3>Comments</h3>
<?php
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'child-grid',
'dataProvider'=>$child_model->searchIncludingComments($parentID),
'filter'=>$child_model,
'columns'=>array(
'date',
'observation',
array(
'class'=>'CButtonColumn',
),
),
));
...
But I must have missed something because when it comes to grid rendering stops - but no error in log
Would be nice if somebody could help me !
I found the solution for me - all my changes and controler are worthless because now I do all stuff in the view :
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'comments-grid',
'dataProvider'=>new CActiveDataProvider('Employeecomment',array(
'criteria'=>array(
'condition'=>'employee_id=:eid',
'params'=>array(':eid'=>$model->id),
),
'sort'=>array(
'defaultOrder'=>'date DESC',
),
)),
Sure there is something I did not understand why it did not work ...

Yii CGridView can't show custom SQL attribute

In the Type model's search() function, I want to display three attributes in CGridview:
type.name, type.description and count(dataset_type.dataset_id)
public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->alias='t';
$criteria->select='t.name, t.description, count(dataset_type.dataset_id) as number';
$criteria->join='LEFT JOIN dataset_type ON dataset_type.type_id=t.id';
$criteria->group='t.id';
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
This is the view:
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id' => 'type-grid',
'dataProvider' => $model->search(),
'filter' => $model,
'itemsCssClass' => 'table table-bordered',
'columns' => array(
'name',
'description',
'number',
array(
'class'=>'CButtonColumn',
),
),
)); ?>
but in this way the columns in CGridView can only display model attributes, it shows type.number can't find in model Type, how can I display the count()?
You will also have to add the attribute to your model to be able to use it as a column in your CGridView:
class Type extends CActiveRecord {
public $number;

Displaying data from two tables in Yii CGridView

I want to show 2 tables with a right join, but the code I wrote does not work as expected. Can anyone tell me what I am doing wrong ?
view : admin.php
$this->widget('bootstrap.widgets.TbGridView', array(
'id' => 'punish-grid',
'dataProvider' => $model->searchJoin(),
'type' => 'striped bordered condensed',
'filter' => $model,
'columns' => array(
array(
'header' => 'No',
'type'=>'raw',
'htmlOptions'=>array('style'=>'width: 25px'),
'value'=>'$this->grid->dataProvider->pagination->currentPage
*$this->grid->dataProvider->pagination->pageSize + $row+1',
),
// i want to display p.kode,p.status from table status
'berlaku_punish',
'nilai',
array(
'class'=>'bootstrap.widgets.TbButtonColumn',
),
),
));
and my model : BasePunish.php
public function relations() {
return array(
'idStatus' => array(self::BELONGS_TO, 'Status', 'id_status'),
);
}
public function searchJoin() {
$criteria = new CDbCriteria;
$criteria->select = 'p.kode,p.status,t.nilai,t.berlaku_punish';
$criteria->join= 'RIGHT JOIN status p ON (t.id_status=p.id)';
$criteria->condition = 't.id_status IS NULL';
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
'sort'=>array(
'defaultOrder'=>'kode ASC',
),
)
);
}
I might really did not understand what you are asking but still if nothing is working for you then you can try this
array(
'header'=>'Products',
'value'=>array($model,'gridCreateUser'),
),
In this, the value will try to find the function gridCreateUser in the class of which $model is the object. In your case i guess $model is the object of the BasePunish.
So in your BasePunish.php create a function gridCreateUser() and then you can return the value which you want to display in your widget.
eg:-
In your BasePunish.php
public function gridCreateUser($data)
{
// you can access the object $data here
// do what ever you want to do
$value='return whatever you want to return';
return $value;
// this $value will be displayed there
}

Inserting value of column from other table into $criteria as value of column of table of current module

What I am trying to do:
I want to print data from table using CGridView, yet one important thing - I need to change value of 'bookId' in $criteria to value of 'bookName' from other table.
How can I do that?
regards.
/// here comes code from model
public function search() {
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria = new CDbCriteria;
$criteria->compare('bookId',$this->bookId);
$criteria->compare('bookBookdetailId', $this->bookBookdetailId);
$criteria->compare('bookState', 1);
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
/// here is code from view
print_r($model);
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider' => $model->search(), 'columns' => array(
'bookCatalgoueNumber',
'bookDescription',
'bookBookdetailId'
),
)
);
/// the name of the model is Book, the other is Bookdetail (and so are the tables)
/// also bookBookdetailId is foregin key that links to Bookdetail.bookdetailId
// I expect that result will the name of the book (bookdetailTitle) to replace bookBookdetailId
If you also want to search/sort by that column, this will probably be the best answer I can give you:
http://www.mrsoundless.com/php/yii/searching-and-sorting-a-column-from-a-related-table-in-a-cgridview/
UPDATE (because I'm guessing you didn't really understand the link. Or simply didn't want to read it because it's long..)
I'm assuming:
You got a relation to your bookdetails table called 'bookdetails'
You got a column in your bookDetails table called 'name'
Step 1: Add this to your model:
private $_name = null;
public function getName()
{
if ($this->_name === null && $this->bookDetails !== null)
{
$this->_name = $this->bookDetails->name;
}
return $this->_name;
}
public function setName($value)
{
$this->_name = $value;
}
Step 2: Now add 'name' to the search rule in the 'rules' function of your Book model
Step 3: Change your 'search' function of your Book model to:
public function search() {
$criteria=new CDbCriteria;
$criteria->with = "bookDetails"; // Make sure you query with the post table.
$criteria->compare('t.bookId',$this->bookId,true);
$criteria->compare('t.bookState',$this->bookState);
$criteria->compare('t.bookBookdetailId',$this->bookBookdetailId,true);
$criteria->compare('bookDetails.name', $this->name,true);
$sort = new CSort();
$sort->attributes = array(
'defaultOrder'=>'t.create_time DESC',
'bookId'=>array(
'asc'=>'t.bookId',
'desc'=>'t.bookId desc',
),
'bookState'=>array(
'asc'=>'t.bookState',
'desc'=>'t.bookState desc',
),
'bookBookdetailId'=>array(
'asc'=>'t.bookBookdetailId',
'desc'=>'t.bookBookdetailId desc',
),
'name'=>array(
'asc'=>'bookDetails.name',
'desc'=>'bookDetails.name desc',
),
);
return new CActiveDataProvider('Book', array(
'criteria'=>$criteria,
'sort'=>$sort
));
}
Step 4: Now add 'name' to your columns array in your CGridView. Should become something like:
'dataProvider' => $model->search(),
'columns' => array(
'bookCatalgoueNumber',
'bookDescription',
'bookBookdetailId',
'name',
),
Step 5: Read the article to understand what's going on.
Step 6: Enjoy
Use it in your admin
array('name' => 'book_id', 'header' => 'Book', 'value' =>'YourModel::getName($data["book_id"])')
getName() must be your function in your model as follows
public function getName($book_id)
{
$sql = "SELECT book_name from `Your Table Name` where `id`='$book_id'";
$command = Yii::app()->db->createCommand($sql);
$rs = $command->queryAll();
return $rs;
}

Yii Relation data issue with HasMany

Currently we have two tables.
Locations and Addresses
Locations are a 1 to many relation to addresses on addresses.location_id.
We are trying to output all addresses related to a specific location in the cgridview:
admin.php
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'locations-grid',
'dataProvider'=>$location->search(),
'filter'=>$location,
'columns'=>array(
'id',
'name',
array(
'name' => 'address',
'value' => 'implode("<br>",CHtml::listData($data->addresses(),"id","address"))',
'filter' => CHtml::activeTextField($location, 'address'),
'type' => 'html',
),/**/
array(
'class'=>'CButtonColumn',
),
),
)); ?>
model (locations.php)
public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->together = true;
$criteria->with = array('addresses');
$criteria->compare('id',$this->id);
$criteria->compare('name',$this->name,true);
$criteria->compare('addresses.address',$this->address,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
Is there a better way of going about getting the address data rather then imploding the $data->addresses function?
You can add a getter method to your Locations model.
public function getAddressNames($separator='<br>')
{
$names = array();
foreach($this->adresses as $address) {
$names[] = $address->address;
}
return implode($separator, $names);
}
Then you can use addressNames like a regular attribute in your gridview.

Categories