Writting query using CDbcriteria for CgridView in YII.? - php

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

Related

Sorting for Custom column in grid view in Yii

I have to check no of products quantity from other table and display it in current grid view. So i created one function in model for getting count of that column.
But my question is How can I sort that custom column (checked_kpl) in grid view.
Here is my code.
MODEL
public function search() {
$criteria = new CDbCriteria;
$criteria->compare('id', $this->id, true);
$criteria->compare('purchase_order_id', $this->purchase_order_id);
$criteria->compare('product_id', $this->product_id);
$criteria->compare('unit_price', $this->unit_price, true);
$criteria->compare('qty', $this->qty, true);
$criteria->compare('cost_price', $this->cost_price, true);
$criteria->compare('customs_percent', $this->customs_percent, true);
$criteria->compare('discount_percent', $this->discount_percent, true);
$criteria->compare('notes', $this->notes, true);
$criteria->compare('created_at', $this->created_at, true);
$criteria->compare('updated_at', $this->updated_at, true);
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
));
}
}
public function getCheckedKpl() {
$checked_kpl = 0;
if (!empty($this->purchaseOrderArrivals)) {
foreach ($this->purchaseOrderArrivals as $eachArrival) {
$checked_kpl += $eachArrival->qty;
}
}
return $checked_kpl;
}
NOTE:
- purchaseOrderArrivals is another model. I already set relation with this model.
- getCheckedKpl function is giving me count of product quantity.
VIEW - In view I put this code in gridview widget for display column.
array(
'name' => 'checked_kpl',
'value' => '$data->getCheckedKpl()',
'type' => 'raw',
'class' => 'DataColumn'
),
Any help will appreciate. thanks.
class Model extends CActiveRecord {
// Adding attribute to work with SQL query
public $checked_kpl;
public function attributeLabels(){
// Prettify column name
return array( 'checked_kpl' => 'Checked kpl' );
}
public function search() {
$criteria = new CDbCriteria;
// Count subquery like this
// SELECT COUNT(*) as checked_kpl, id FROM {{table}} GROUP BY param
// Condition like this
// ( q1.id=t.id )
$criteria->join = "LEFT JOIN (/* **HERE IS A COUNT SUBQUERY** */) as q1 ON(/* **HERE IS A CONDITION** */)";
$criteria->select = array( '*', new CDbExpression("q1.checked_kpl as checked_kpl") );
// ... your criteria here
// Adding custom sort data
$sort = new CSort();
$sort->attributes = array(
'checked_kpl' => array(
'asc' => 'q1.checked_kpl',
'desc' => 'q1.checked_kpl DESC'
)
);
return new CActiveDataProvider( $this, array(
'criteria' => $criteria,
'sort' => $sort,
) );
}
}

merge two CActiveDataProvider and show result in a CGridview in yii

I have 2 model :
$model = new ProfileInformation('internetConection');
$modeliner = new ProfileInformation('inerConection');
I show those in 2 CGridView in yii how can show in a CGridView
Model:
public function internetConection() {
// #todo Please modify the following code to remove attributes that should not be searched.
$criteria = new CDbcriteria();
$criteria->with = array('user');
$criteria->condition = 'serviceId=:serviceId';
$criteria->params = array(':serviceId' => '1');
$criteria->group = 't.user_Id';
$criteria->select = array('count(distinct psh_profile_information_services.profileInformationId) AS internetConectionCount');
$criteria->join = 'left join psh_profile_information_services on t.id=psh_profile_information_services.profileInformationId';
$criteria->order = 't.id';
$criteria->compare('user_Id', $this->user_Id);
$criteria->compare('isService', $this->isService, true);
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
));
}
public function inerConection() {
// #todo Please modify the following code to remove attributes that should not be searched.
$criteria = new CDbcriteria();
$criteria->with = array('user');
$criteria->addInCondition('serviceId', array(2, 3, 4, 5));
$criteria->group = 't.user_Id';
$criteria->select = array('count(distinct psh_profile_information_services.profileInformationId) AS inerConectionCount');
$criteria->join = 'left join psh_profile_information_services on t.id=psh_profile_information_services.profileInformationId';
$criteria->order = 't.id';
$criteria->compare('user_Id', $this->user_Id);
$criteria->compare('isService', $this->isService, true);
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
));
}
I am using 2 CgridView now , but if i can show in a table it is very good.
eache result search have a new field : inerConectionCount and internetConectionCount.
table for internetConectionCount
table for inernetConectionCount
I want it:
$this->widget('zii.widgets.grid.CGridView', array(
'id' => 'profile-information-grid1',
'dataProvider' => $dataprovider
'columns' => array(
array(
'header' => '',
'value' => '$this->grid->dataProvider->pagination->offset + $row+1', // row is zero based
),
array(
'name' => 'ProfileInformation.user.organization',
'value' => 'CHtml::encode($data->user->organization)',
),
array(
'name' => 'ProfileInformation.user.scope',
'value' => 'CHtml::encode($data->user->scope->name)',
'filter' => Scope::model()->options,
),
array(
'name' => 'id',
'value' => 'CHtml::encode($data->id)',
),
'inerConectionCount',
),
));
You can combine data from two providers, but you have to disable pagination or it will limit to 10 record in each providers
$model = new ProfileInformation('internetConection');
$modeliner = new ProfileInformation('inerConection');
$data = CMap::mergeArray( // combine two data
$model->search()->getData(),
$modeliner ->search()->getData()
);
$provider = new CArrayDataProvider( $data ); // use CArrayDataProvider instead of CActiveDataProvider

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