Displaying data from two tables in Yii CGridView - php

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
}

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 ...

Displaying Virtual Attribute In CGridView

I have used a from_date & to_date attributes to search my data and have placed it in the Model as safe attributes. Now I want to display the same from_date and to_date in the CGridview with other data from the model.
Shouldn't I just be able to use $data->from_date in my CGridView?
Model
public $from_date;
public $to_date;
public function rules() {
array('from_date, to_date', 'safe', 'on'=>'search'),
}
public function search(){
//....
if(!empty($this->to_date) && !empty($this->from_date))
{
$criteria->addCondition("date($created_date) >= '$this->from_date' and date($created_date) <= '$this->to_date'");
}
else if(!empty($this->from_date) && empty($this->to_date))
{
$criteria->addCondition("date($created_date) >= '$this->from_date'");
}
else if(!empty($this->to_date) && empty($this->from_date))
{
$criteria->addCondition("date($created_date) <= '$this->to_date'");
}
//....
}
Controller
$model = new Tickets('search');
if (!empty($_GET)) {
$model->ticket_id = isset($_GET['ticket_id']) ? $_GET['ticket_id'] : '';
$model->from_date = isset($_GET['from_date']) ? $_GET['from_date'] : '';
$model->to_date = isset($_GET['to_date']) ? $_GET['to_date'] : '';
}
$this->render('search', array(
'model' => $model
));
View
$this->widget('bootstrap.widgets.TbGridView', array(
'type' => 'striped bordered condensed',
'dataProvider' => $model->search(),
'columns' => array(
array(
'name' => 'From date',
'type' => 'html',
'value' => '$data->from_date',
),
),
));
Try the following adjustments. I don't see where you specified how the $_GET attributes were being set, so I included the standard way of doing it with CGridView. Let me know if it works.
Controller:
$model = new Tickets('search');
//remove any default values
$model->unsetAttributes();
//set the attributes based on the standard syntax of how CGridview populates GET
if (!empty($_GET['Tickets'])) {
$model->attributes = $_GET['Tickets'];
}
$this->render('search', array(
'model' => $model
));
Model: add ticket_id to rules, to automatically process set it if present.
public function rules() {
array('from_date, to_date, ticket_id', 'safe', 'on'=>'search'),
}
View:
$this->widget('bootstrap.widgets.TbGridView', array(
'type' => 'striped bordered condensed',
'dataProvider' => $model->search(),
'filter'=>$model,//should provide default filtering
'columns' => array(
array(
'name' => 'From date',
'type' => 'html',
'value' => '$data->from_date',
),
),
));
Side note: Your model's search method had huge SQL injection vulnerabilities, but let's solve one problem at a time first.

Writting query using CDbcriteria for CgridView in YII.?

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'),
)

Displaying attributes from another model using CGRIDVIEW

I have 2 tables/models:
Tmp1
Header
QuestionText
Tmp2
Header
Part
OutOf
I'm trying to display the columns: Header, QuestionText, Part, OutOf
in a single CGRIDVIEW.
In Tmp1 model:
public function relations()
{
return array(
'tmp2s' => array(self::HAS_MANY, 'Tmp2', 'Header'),
);
}
In Tmp2 Model:
public function relations()
{
return array(
'header' => array(self::BELONGS_TO, 'Tmp1', 'Header'),
);
}
Controller:
public function actionReviewAll()
{
$tmp1 = new Tmp1('search');
$tmp1->unsetAttributes();
if(isset($_GET['Tmp1'])){
$model->attributes=$_GET['Tmp1'];
}
$this->render('ReviewAll',array(
'tmp1'=>$tmp1,
));
}
View:
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'tmp-grid',
'dataProvider'=>$tmp1->search(),
'filter'=>$tmp1,
'columns'=>array(
'Header',
'QuestionText',
array(
'name' => 'tmp2.OutOf',
'value' => '$data->tmp2[0].OutOf',
'type' => 'raw'
),
),
)); ?>
Error:
Property "Tmp1.tmp2" is not defined.
Any help is greatly appreciated
You have a sintax error:
Tmp1.tmp2 = Tmp1.tmp2s
The relation alias is with 's'. "tmp2s".
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'tmp-grid',
'dataProvider'=>$tmp1->search(),
'filter'=>$tmp1,
'columns'=>array(
'Header',
'QuestionText',
'tmp2s.Part',
'tmp2s.OutOf',
),
)); ?>
But you are trying to show a 'self::HAS_MANY' relationship, you can't show that on a normal CGridView widget...
Your code probably works (I haven't tried it), but not in cases where your tmp1 model has no tmp2's. You must make sure there is a tmp2 before accessing it:
'value' => 'isset($data->tmp2) ? $data->tmp2[0].OutOf : Null',
You can also pass a function($data,$row) to value to make it look less messy. (Yes, that's important to me.)

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;
}

Categories