I'm aware that similar questions have been asked, sorry, but I can't for the life of me see what I'm doing wrong. Any help would be greatly appreciated. All I want to do is to add an extra column to a CGridView that displays a total of two values in the database.
These are the steps I've taken:
Database
User(forename, surname, part1, part2)
class User extends Controller:
protected function getTotal($data,$row,$dataColumn){
return $data->getAttribute('part1')+$data->getAttribute('part2');
}
public function actionIndex(){
$dataProvider=new CActiveDataProvider('User');
$this->render('index',array(
'dataProvider'=>$dataProvider,
));
}
class Stadium extends CActiveRecord:
public function rules(){
return array(
array('forename, surname', 'required'),
array('forename', 'surname', 'max'=>50),
array('part1, part2', 'numerical', 'integerOnly'=>true),
array('forename, surname, part1, part2, total', 'safe', 'on'=>'search'),
);
}
public function attributeLabels()
{
return array(
'forename' => 'forename',
'surname' => 'surname',
'part1' => 'part1',
'part2' => 'part2',
'total' => array(
'asc'=>'part1 + part2',
'desc'=>'part1 + part2 desc',
),
);
}
public function search(){
$criteria=new CDbCriteria;
$criteria->compare('forename',$this->forename,true);
$criteria->compare('surname',$this->surname,true);
$criteria->compare('part1',$this->part1);
$criteria->compare('part2',$this->part2);
$criteria->compare('total',$this->part1 + $this->part2,true);
$sort = new CSort();
$sort->attributes = array(
'total'=>array(
'asc'=>'part1 + part2 ASC',
'desc'=>'part1 + part2 DESC',
),
'*',
);
return new CActiveDataProvider(User', array(
'criteria'=>$criteria,
'sort'=>$sort,
));
}
}
view/User/index.php
<?php $this->widget('zii.widgets.grid.CGridView', array(
'itemsCssClass'=>'table table-hover',
'dataProvider'=>$dataProvider,
'template'=>"{items}",
'columns'=>array(
array('name'=>'forename', 'header'=>'Forename'),
array('name'=>'surname', 'header'=>'Surname'),
array('name'=>'total', 'header'=>'Total', 'value'=>array($this, 'getTotal')),
),
)); ?>
<?php $this->endWidget();?>
Thanks a lot for any advice.
Solution:
Ok here is what you need to do:
class Stadium extends CActiveRecord:
public $total; //add this line
//your rules should be fine
//don't know if you need the asc and desc on attribute labels i just have one
'total' => 'Total',
$criteria->compare('total',$this->total); //change this line
//i didn't use a Csort you might be able to but this is they way i did it
return new CActiveDataProvider(User', array(
'criteria'=>$criteria,
'sort'=> array(
'attributes' => array(
'total'=>array(
'asc'=>'(part1 + part2) ASC',
'desc'=>'(part1 + part2) DESC',
),
'*',
),
),
));
//add this inside your model also
public function afterFind() {
parent::afterFind();
$this->total = $this->part1+ $this->part2;
return;
}
Everything else in your model is fine. Then on your CGridView just change the one line:
array('name'=>'total', 'header'=>'Total'), //don't need to set value it is part of the model like other columns now
http://www.yiiframework.com/forum/index.php/topic/21114-create-now-model-variable/
Original Answer:
I believe if you are going to use a CSort object you need to add it to the CActiveDataProvider using setSort() or you don't have to create a CSort you can put it straight into DataProvider.
Option 1:
$sort = new CSort();
$sort->attributes = array(
'total'=>array(
'asc'=>'part1 + part2 ASC',
'desc'=>'part1 + part2 DESC',
),
'*',
);
$data = new CActiveDataProvider(User', array(
'criteria'=>$criteria,
));
$data->setSort($sort);
return $data;
Option 2:
return new CActiveDataProvider(User', array(
'criteria'=>$criteria,
'sort'=> array(
'attributes' => array(
'total'=>array(
'asc'=>'part1 + part2 ASC',
'desc'=>'part1 + part2 DESC',
),
'*',
),
),
));
This may help
http://www.yiiframework.com/wiki/381/cgridview-clistview-and-cactivedataprovider/#hh11
http://www.yiiframework.com/doc/api/1.1/CDataProvider#setSort-detail
Pitchinnate's answer might help you, also, I've noticed a tendency from your part that you put commas where they shouldn't be present. For example
instead of:
$sort->attributes = array(
'total'=>array(
'asc'=>'part1 + part2 ASC',
'desc'=>'part1 + part2 DESC',
),
'*',
);
you need:
$sort->attributes = array(
'total'=>array(
'asc'=>'part1 + part2 ASC',
'desc'=>'part1 + part2 DESC'
),
'*'
);
you should get rid of all the commas put after the last element.
Related
The following Criteria works fine:
$criteria = new CDbCriteria(array(
'condition' => 'Id_menu = 1 ',
'select' => 'name',
'limit' => 5,
));
$dp1 = new CActiveDataProvider('post', array(
'criteria' => $criteria
));
However specifying Criteria directly on a model does not - it has no effect:
$criteria = new CDbCriteria(array(
'condition' => 'Id_menu = 1 ',
'select' => 'name',
'limit' => 5,
));
$dp1 = new CActiveDataProvider(Mdlfood::model()->find($criteria),array(),));
The following also does not work:
$criteria = new CDbCriteria(array(
'condition' => 'Id_menu = 1 ',
'select' => 'name',
'limit' => 5,
));
$model1 = new Mdlfood;
$model1->findAll($criteria);
$dp1 = new CActiveDataProvider($model1,array(),));
Can anyone explain why I cannot declare this configuration directly?
Added mdlfood
class Mdlfood extends CActiveRecord{
public function tableName()
{
return 'tblfood';
}
public function rules()
{
return array(
array('name, Url_picture, Price, Aboute, Id_foodType, Id_menu', 'required'),
array('name', 'length', 'max'=>100),
array('Url_picture, Aboute', 'length', 'max'=>2048),
array('Price, Id_foodType, Id_menu', 'length', 'max'=>20),
array('Id, name, Url_picture, Price, Aboute, Id_foodType, Id_menu', 'safe', 'on'=>'search'),
);
}
public function relations()
{
return array(
'idMenu' => array(self::BELONGS_TO, 'Tblrestmenu', 'Id_menu'),
'idFoodType' => array(self::BELONGS_TO, 'Tblfoodtype', 'Id_foodType'),
);
}
public function attributeLabels()
{
return array(
'Id' => 'ID',
'name' => 'Name',
'Url_picture' => 'Url Picture',
'Price' => 'Price',
'Aboute' => 'Aboute',
'Id_foodType' => 'Id Food Type',
'Id_menu' => 'Id Menu',
);
}
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,true);
$criteria->compare('name',$this->name,true);
$criteria->compare('Url_picture',$this->Url_picture,true);
$criteria->compare('Price',$this->Price,true);
$criteria->compare('Aboute',$this->Aboute,true);
$criteria->compare('Id_foodType',$this->Id_foodType,true);
$criteria->compare('Id_menu',$this->Id_menu,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
public static function model($className=__CLASS__)
{
return parent::model($className);
}
}
But, I think this is not related to Model, because this Criteria work properly in the ActiveDataProvider.
Please try like this,
extra closing brackets, find()-> not in proper format
$criteria=new CDbCriteria(array(
'condition'=>'Id_menu = 1 ',
'select'=>'name',
'limit'=>5,
));
$dp1 = new CActiveDataProvider(Mdlfood::model()->find($criteria),array()); // extra closing brackets
Second way,
$criteria=new CDbCriteria(array(
'condition'=>'Id_menu = 1 ',
'select'=>'name',
'limit'=>5,
));
$model1 = new Mdlfood;
$model1->findAll($criteria);
$dp1 = new CActiveDataProvider($model1,array());
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 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
}
I want to show list of my attributes (id, name, price, discount) and (total_price)column that is not an attribute.
when I use this code, it shows table of data but I can not search or sort in column (total_price)
Can anyone hep me?
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'product-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'id',
'name',
array(
'header' =>'Price',
'name'=>'price',
'value'=>'$data->price',
),
array(
'header' =>'Discount',
'name'=>'discount',
'value'=>'$data->discount',
),
array(
'header' =>'total price',// total price doesn't save in Data Base
'name'=>'total_price',
'value'=>'total_price - (total_price * $data->discount/100)',
),
array(
'class'=>'CButtonColumn',
),
),
));
?>
You can put on $model->search() method this:
$criteria=new CDbCriteria;
$criteria->select = "t.*, t.price - (t.price * t.discount/100) as total_price";
// EDITED: Added for Sort:
$sort = new CSort();
$sort->attributes = array(
'defaultOrder'=>'name ASC',
'total_price'=>array(
'asc'=>'total_price ASC',
'desc'=>'total_price DESC',
),
'*', // Add order in the other fields.
);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'sort'=>$sort, // Added to sort.
);
And create a not persistence attribute on "Product" model Class:
public $total_price;
Finally put 'total_price' on rules() in array with ('safe', 'on'=>'search'), something like this:
array('id, name, price, discount, total_price', 'safe', 'on'=>'search'),
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.