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.
Related
I have a HAS_MANY relation between 2 models, i use bookID as foreign key
model 1 - Importedbooks, Importedbooks can have many CountryOfImport
public function relations()
{
return array(
'CountryOfImportObj'=>array(self::HAS_MANY, 'CountryOfImport', 'bookID')
);
}
model 2 CountryOfImport, CountryOfImport belongs to Importedbooks
public function relations()
{
return array(
'ImportBooksObj'=>array(self::BELONGS_TO, 'Importedbooks', 'bookID')
);
}
Now, For my CGridView i am using a model->search()of the Importedbooks model as my dataProvider, From here is where i get stuck.
CGridView
$data = $model->search();
$data->setPagination(array('pageSize'=>'5'));
$data->criteria->addCondition('active = "yes"');
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$data
,'filter'=>$model
,'pager'=>array('header'=>'')
,'columns'=>array(
'id',
'bookYear',
'bookTitle',
'DISPLAY VALUE FROM OTHER model HERE'
)
)
);
DataProvider of the Imported books model, i'm using this as my data provider for the grid
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('id',$this->id);
$criteria->compare('bookID',$this->bookID);
$criteria->compare('countryName',$this->countryName,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
The relation works because i can use below code in my controller to get a field(countryName) from the other model
$model = Importedbooks::model()->with('CountryOfImportObj')->findbyPK(3);
print_r($model->CountryOfImportObj[0]->countryName);
Such as Importedbooks have many CountryOfImport, in one row you must show or all country names or concreet names depending on ID or countryName or some other attribute.
You can pass anonymous function as value:
'columns' => array(
'id',
'bookYear',
'bookTitle',
array(
'header' => 'Countries',
'type' => 'raw',
// if you have defined counrtyName attribute in 'Importedbooks' model, if not you can remove this row
// also CGridView 'uses' attribute 'name' for filtering or sorting
'name' => 'countryName',
'value' => function($data, $row) { //$data is item of DataProvider, $row is number of row (starts from 0)
$countries = CHtml::listData((array)$data->CountryOfImportObj, 'id', 'countryName');
return implode(', ', $countries);
}
)
)
If you want to filter or sort by external attributes too, you must "declare them"
Thanks!
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 ...
I am trying to show my data in gridview and in process have written the following query which I am trying to write using CDBCriteria,
//query
SELECT user. * , jobs. * , COUNT( jobs.user_id )
FROM user
INNER JOIN jobs ON user.id = jobs.user_id
GROUP BY user.id
I have tried the following thing:
$criteria = new CDbCriteria;
$criteria->select ='user.*,jobs.*';
$criteria->select ='COUNT(jobs.user_id)';
$criteria->select ='user';
$criteria->join ='INNER JOIN jobs ON user.id = jobs.user_id';
$criteria->group ='user.id';
return new CActiveDataProvider('manageemployers', array(
'criteria'=>$criteria,
my view have the following code.
<?php
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider' =>$model->search(),
// 'filter' => $model,
'columns' => array(
array(
'name' => ' Employer ID',
'type' => 'raw',
'value' => 'CHtml::encode($data->id)',
'htmlOptions' => array('style'=>'width:90px;','class'=>'zzz'),
// 'filter'=>'false' /* for hiding filter boxes */
[...]
?>
My contoller
public function actionManageEmployers() {
$user_id = Yii::app()->session['user_id'];
if (Yii::app()->user->getId() === null)
$this->redirect(array('site/login'));
$model = new ManageEmployers();
$model->user_id = $user_id;
$this->render('manageemployers', array('model' => $model,
));
}
But its not working. Please help me on this one. Thanks!
If you have table relations set up, then in your User model (that refers to your user table) try writing your CDbCriteria like so:
$criteria = new CDbCriteria();
$criteria->with = array('jobs' => array('joinType' => 'STRAIGHT_JOIN'));
$criteria->together = true;
$criteria->addCondition('id = jobs.user_id');
return new CActiveDataProvider('manageemployers', array(
'criteria' => $criteria
));
EDIT
So now I'm able to understand your problem and I tried to fix it with this.
i think i had the solution, you don't need to get the data in the search() like you did it. you can use relations and other stuff to get your data.
firstly i would add a relation to your user-model like this:
'jobs' => array(self::HAS_MANY, 'Jobs', 'user_id')
after that, you can access all jobs of the user with $model->jobs
then you need to undo your changes of the search()-function. I mean that it must look like this:
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('attribute',$this->attribute);
//this is just an example ^
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
changes in the action:
$model = new ManageEmployers();
to this:
$model = new ManageEmployers("search");
changes in the view:
add something like this to your colums array:
array(
'name' => 'Total Jobs Posted',
'value' => 'count($data->jobs)',
'htmlOptions' => array('style'=>'width:90px;','class'=>'zzz'),
)
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;
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.)