Yii Framework : Join table (or other SQL) in data provider? - php

Background
I have used Gii Crud Generator with my "Category" model, and I want to modify the admin form.
I look inside "protected/views/Category/admin.php,
I found the table is render by a widget('zii.widgets.grid.CGridView'),
and it using a data Provider for it's data.
I suppose I can find some where to input the SQL query in the data Provider, but I don't understand about how's it works.
these is the code In the Model->relations(), but I don't know what to do next.
public function relations(){
return array(
'cateLang' => array(self::HAS_MANY, 'CategoryLang', 'cate_id')
);
}
where the data provider is generated :
public function search(){
$criteria=new CDbCriteria;
$criteria->compare('id',$this->id);
$criteria->compare('status',$this->status,true);
$criteria->compare('createDate',$this->createDate,true);
$criteria->compare('updateDate',$this->updateDate,true);
$criteria->compare('remark',$this->remark,true);
return new CActiveDataProvider($this->with('cateLang'), array(
'criteria'=>$criteria,
));
}
Target
I want to add two more columns at the table of "protected/views/Category/admin.php,
which will show French Title & English Title of the row.
To get data in SQL, it will be :
SELECT
cate.id,
lang1.name as "FrenchTitle",
lang2.name as "EnglishTitle",
cate.updateDate,
cate.createDate,
cate.remark
FROM `category` cate
LEFT JOIN `categorylang` lang1
ON `lang1`.`cate_id` = `cate`.id
AND `lang1`.`lang_id`= 1
LEFT JOIN `categorylang` lang2
ON `lang2`.`cate_id` = `cate`.id
AND `lang2`.`lang_id`= 2
WHERE cate.status = 'live'
If I can done with data Provider, the CGridView parameter may be like this :
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'category-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'id',
'FrenchTitle',
'EnglishTitle',
'createDate',
'updateDate',
'remark',
array(
'class'=>'CButtonColumn',
),
),
));

You could try the following:
public function search(){
$criteria=new CDbCriteria;
$criteria->compare('id',$this->id);
$criteria->compare('status',$this->status,true);
$criteria->compare('createDate',$this->createDate,true);
$criteria->compare('updateDate',$this->updateDate,true);
$criteria->compare('remark',$this->remark,true);
$criteria->with = array('cateLang' => array(
'condition' => 'cateLang.id = 1 OR cateLang.id = 2',
'order' => 'cateLang.id ASC'
));
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'category-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'id',
array(
'name' => 'FrenchTitle'
'value' => '(isset($data->cateLang[0])) ? $data->cateLang[0]->name : "no Title"',
),
array(
'name' => 'EnglishTitle'
'value' => '(isset($data->cateLang[1])) ? $data->cateLang[1]->name : "no Title"',
),
'createDate',
'updateDate',
'remark',
array(
'class'=>'CButtonColumn',
),
),
));
In the search I specify that I want only cateLang object with the id 1 or 2 and then in the cgridview I display a relational object.

Related

Yii CGridView and default values in CDbCriteria

I have simple CGridView, which is not showing me any data at all.
I've logged query built by CDbCriteria and there was some LIKE conditions which uses mysql default field values, so MySQL searches for entries with default values in required fields.
Since I have none entries matching this condidion it returns 0 rows. But the thing is, I don't need these LIKEs. Is there a way to disable it?
Here's the view:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider' => $model->search(),
'filter' => $model,
'columns' => array(
array(
'name' => 'name',
'type' => 'raw',
'value' => 'CHtml::encode($data->name)'
),
array(
'name' => 'email',
'type' => 'raw',
'value' => 'CHtml::link(CHtml::encode($data->email), "mailto:".CHtml::encode($data->email))',
),
),
));
Controller:
public function actionUsers() {
$model = new Users();
$this->renderPartial('users',array(
'model' => $model,
));
}
Function Search of model Users:
return new CActiveDataProvider(get_class($this), array(
'criteria'=>$criteria,
'sort'=>array(
'defaultOrder'=>'user ASC',
),
'pagination'=>array(
'pageSize'=>5
),
));
And Logged Query:
SELECT * FROM `users` `t` WHERE (((((email LIKE :ycp0) AND (`group` LIKE :ycp1)) AND (gender LIKE :ycp2)) AND (city LIKE :ycp3)) AND (name LIKE :ycp4)) AND (av_url LIKE :ycp5) ORDER BY `t`.`name` LIMIT 5. Bound with :ycp0='%NotSet%', :ycp1='%3%', :ycp2='%Secret%', :ycp3='%NotSet%', :ycp4='%NotSet%', :ycp5='%noav.jpg%'
I am new to Stackoverflow and don't have sufficient reputation to post a comment, otherwise I would have asked that you share more information on how you configure your CDbCriteria object in your $model->search() function.
But, I suspect that you are using partial matches in the compare method, which can be disabled by passing false in the $partialMatch parameter as follows:
$criteria = new CDbCriteria;
$criteria->compare('email', $someValue, false);
Or, since false is the default value, you can simple write:
$criteria->compare('email', $someValue);

Yii TbGridView set filter dropdown html attributes

I am unable to figure out how to set the filter dropdown's id attribute.
Here is the view code that defines the widget.
$this->widget('bootstrap.widgets.TbGridView',array(
'id'=>'view-grid',
'enableHistory'=>true,
'dataProvider'=>$model->search(),
'summaryText'=>"",
'filter'=>$model,
'columns'=>array(
array('name'=>'v_id','htmlOptions'=>array('style'=>'width: 60px')),
array('name'=>'v_parent_view','htmlOptions'=>array('style'=>'width: 20%'),'value'=>'$data->vParent->v_name'),
array('name'=>'v_name','type'=>'raw','value'=>function($data,$row) {
if(isset($data->vLatestVersion[0]->vv_id) && $data->vLatestVersion[0]->vv_id) {
return CHtml::link($data->v_name,array("viewVersion/update","id"=>$data->vLatestVersion[0]->vv_id));
} else {
return CHtml::link($data->v_name,array("viewVersion/create","vid"=>$data->v_id));
}
}),
array('name'=>'v_date_modified', 'type'=>'raw', 'htmlOptions'=>array('style'=>'width: 110px'), 'value'=>function($data, $row) {
return $data->modified_since . '<br/><span class="timeago">'.$data->vUserModified->username.'</span>';
}),
array(
'name'=>'v_status',
'value'=>'$data->getStatusName()',
'filter'=>Yii::app()->params['globalDmpLookups']['generalStatus'],
'filterHtmlOptions'=>array('id'=>'sel_status'),
'htmlOptions'=>array('style'=>'width: 60px'),
)
),
));
The line of code near the end that has 'filterHtmlOptions' is what I tried, but it is not working. Any help would be greatly appreciated.
The rendered html of my dropdown should look like this:
<select id="sel_status" name="View[v_status]">...</select>
But sadly it looks like this:
<select name="View[v_status]">...</select>
I found that I was trying to use a dropdown list incorrectly in my list filter for status = Active/Disabled. Doing this the Yii way is a simple matter of setting up the model like this...
public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->with = array('ggUserModified'); // specify relationship
$criteria->compare('gg_id',$this->gg_id);
$criteria->compare('gg_class',$this->gg_class,true);
$criteria->compare('gg_name',$this->gg_name,true);
$criteria->compare('gg_title',$this->gg_title,true);
$criteria->compare('gg_description',$this->gg_description,true);
$criteria->compare('gg_date_modified',$this->gg_date_modified,true);
$criteria->compare('gg_status',$this->gg_status);
$criteria->compare('User.username',$this->gg_user_modified_rel,true); // use table alias name and specify relationship field property
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'sort'=>array(
'attributes'=>array(
'gg_user_modified_rel' => array( // specify relationship field property
'asc'=>'User.username', // specify table alias name
'desc'=>'User.username DESC', // specify table alias name
),
'*',
),
),
));
}
... and setting up the view like this...
<?php $this->widget('bootstrap.widgets.TbGridView',array(
'id'=>'gallery-group-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'gg_id',
'gg_name',
array(
'name'=>'gg_user_modified_rel', // specify relationship field property
'value'=>'$data->ggUserModified->username' // specify relationship name
),
'gg_date_modified',
array(
'name'=>'gg_status',
'value'=>'$data->getStatusName()',
'filter'=>Yii::app()->params['globalDmpLookups']['generalStatus'],
'htmlOptions'=>array('style'=>'width: 120px'),
),
array('header'=>'Item Count','value'=>'$data->ggChildCount'),
array(
'class'=>'bootstrap.widgets.TbButtonColumn',
),
),)); ?>
filterHtmlOptions is the HTML options for the table row element, not for the input.
what is the value of Yii::app()->params['globalDmpLookups']['generalStatus']?
if you want to set the filter dropdown's id attribute, set the HTML attributes on the dropdown.
for example :
// ..
'columns'=>array(
array(
'name' => 'majorId',
'filter' => CHtml::activeDropDownList($model, 'majorId', CHtml::listData(
Major::model()->findAll(), "id", "name"),
array(
'empty' => '=== Pilih Jurusan ===',
'id' => 'YOUR_ID'
)
),
),
),
// ..

pageSize bug in yii grid when using joins

I have this search using joins. The results are correct but yii grid does not show all of the results even if the pagesize selected is greater than number of result.
here's my code :
if($_GET['BaseIar']['description'] !='empty'){
$criteria->with = array('class','classSi',);
$this->description=$_GET['BaseIar']['description'];
$criteria->compare('class.description', $this->description, true);
$criteria->compare('classSi.description', $this->description, true, 'OR');
}
here are the relations:
public function relations() {
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'class' => array(self::HAS_ONE, 'BaseEiEquipItem', 'iar_no'),
'classSi' => array(self::HAS_ONE, 'BaseSiReceivedItem','iar_no'),
);
}
here's the grid:
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'base-iar-grid',
'dataProvider'=>$searchModel->search(),
'columns'=>array(
array(
'class'=>'CCheckBoxColumn',
'id'=>'base-iar-id',
'selectableRows'=>2, // multiple rows can be selected
),
'iar_id',
'dateInspected',
array(
'name'=>'inspectedBy',
'value'=>'(!empty($data->inspectedBy))?$data->inspectedBy0->person->lastName.", ".$data->inspectedBy0->person->firstName." ".$data->inspectedBy0->person->middleName:"---"',
),
array(
'name'=>'endUser',
'value'=>'(!empty($data->endUser))?$data->endUser0->person->lastName.", ".$data->endUser0->person->firstName." ".$data->endUser0->person->middleName:"---"',
),
'dateReceived',
array(
'name'=>'receivedBy',
'value'=>'(!empty($data->receivedBy))?$data->receivedBy0->person->lastName.", ".$data->receivedBy0->person->firstName." ".$data->receivedBy0->person->middleName:"---"',
),
array(
'name'=>'requisitionOffice',
'value'=>'(!empty($data->requisitionOffice))?$data->requisitionOffice0->code:"---"',
'value'=>'$data->requisitionOffice0->code'
),
'prNo',
'poNo',
array(
'class'=>'InfosysButtonColumn',
'template'=>'{view}',
'afterDelete'=>'function(link,success,data){
if(success){
jSuccess("Delete completed successfully!");
}
}',
'buttons'=>array(
'view' => array(
'label' => 'View details',
'url' => 'Yii::app()->createUrl("pims/IAR/BaseIar/view", array("id"=>$data["id"]))'
),
),
'header'=>CHtml::activeDropDownList($model,'pageSize',array('10'=>'10','20'=>'20','30'=>'30','50'=>'50','100'=>'100','ALL'=>'All'),array('onchange'=>'$.fn.yiiGridView.update("base-iar-grid", {data:{pageSize:$(this).val()}});')),
),
)
));
What might be the correct way to declare multiple relations in $criteria->with?
Hey I found this piece of example code in the docs for with(), maybe it'll help you:
Post::model()->with(array(
'author'=>array('select'=>'id, name'),
'comments'=>array('condition'=>'approved=1', 'order'=>'create_time'),
))->findAll();

cgridview related fields filtering

I have a problem that I have solved for all but one of the cgridview filters, which is a related field.
I am using a solution Seenivasan has supplied but the related field status does not get added to the string.
here is the cgridview :-
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'tbl-orders-grid',
'dataProvider'=>$dataProvider,
'afterAjaxUpdate'=>"function() {
jQuery('#Orders_date_first').datepicker(jQuery.extend({showMonthAfterYear:false}, jQuery.datepicker.regional['id'], {'showAnim':'fold','dateFormat':'yy-mm-dd','changeMonth':'true','changeYear':'true','constrainInput':'false'}));
jQuery('#Orders_date_last').datepicker(jQuery.extend({showMonthAfterYear:false}, jQuery.datepicker.regional['id'], {'showAnim':'fold','dateFormat':'yy-mm-dd','changeMonth':'true','changeYear':'true','constrainInput':'false'}));
}",
'filter'=>$model,
'columns'=>array(
array(
'name'=>'id',
'type'=>'raw',
'value'=>'str_pad($data->id,8-strlen($data->id),"0",STR_PAD_LEFT)',
'htmlOptions'=>array('style' => 'text-align: right;width: 60px;')
),
array(
'name'=>'date_order_placed',
'filter'=>$dateisOn,
'value'=>'date("d-m-Y",strtotime($data->date_order_placed))',
),
array(
'name'=>'status',
'type'=>'raw',
//'htmlOptions'=>array('id' => 'order_status_search'),
'value'=>'CHtml::value($data,"status.orders_status_name")',
'filter'=>CHtml::listData(OrderStatus::model()->findAll(
array(
'select'=>array('orders_status_name'),
'distinct'=>true
)),"orders_status_name","orders_status_name")//this is the focus of your code
),
array(
'class'=>'EButtonColumnWithClearFilters',
'clearVisible'=>true,
'template'=>'{view}{email}',
'buttons'=>array
(
'email' => array
(
'label'=>'Reprint invoice and email to yourself',
'imageUrl'=>Yii::app()->request->baseUrl.'/images/email.png',
'url'=>'Yii::app()->createUrl("orders/ureprint", array("id"=>$data->id))',
),
),
),
),
)); ?>
here is the php and js that adds the current filter values to the url.
echo CHtml::button('List Orders',array('id'=>'listelement'));
Yii::app()->clientScript->registerSCript('test','
$("body").on("click","#listelement",function(){
var str="&";
$.each($("#tbl-orders-grid input").serializeArray(),function(i,j){
str=str+j.name+"="+j.value+"&";
});
window.location="'.CHtml::normalizeUrl(array('orders/index')).'"+str;
});
');
The other filters, dates and id, work perfectly. They are added to the url above. Status is not.
1- you need to define new filters in your model serach() methode for example like
$criteria->compare('Restaurant.Name',$this->Name,true);
Restaurant is your relation key , name : value from another table related to this fk
2- you have to add value of gridview column like :
view:
array(
'name' => 'Restaurant.Name',
'header' => 'Username',
'filter' => CHtml::activeTextField($model, 'name'),
'value' => '$data->Restaurant->Name',
This link will help you
yii CGridView filter with relations

Add column as link in CGridView

I need to add link to my gridview this link will call action with parameters like
user_id and course_id .
so i wrote this code
View :
<?php
$cmodel=new Courses;
$user_id=intval($_GET['user_id']);
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'courses-grid',
'dataProvider'=>$cmodel->searchCources($user_id),
'filter'=>$cmodel,
'columns'=>array(
'course_id',
'name_ar',
'name_en',
'code',
't_time',
array(
'name' => 't_time',
'value' => "CHtml::link('Add',array('packages/add','user_id'=>$user_id,'course_id'=>$data->course_id))",
'type' => 'raw',
)
,
/*
'req',
'aud',
'targets',
'programs',
'criterion',
'section_id',
'acc',
'en',
'ar',
'fr',
'image',
*/
)));
?>
Model :
<?php
...
public function searchCources($user_id)
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('course_id',$this->course_id);
$criteria->compare('name_ar',$this->name_ar,true);
$criteria->compare('name_en',$this->name_en,true);
$criteria->compare('code',$this->code,true);
$criteria->compare('t_time',$this->t_time);
$criteria->compare('intro',$this->intro,true);
$criteria->compare('req',$this->req,true);
$criteria->compare('aud',$this->aud,true);
$criteria->compare('targets',$this->targets,true);
$criteria->compare('programs',$this->programs,true);
$criteria->compare('criterion',$this->criterion,true);
$criteria->compare('acc',$this->acc);
$criteria->compare('en',$this->en);
$criteria->compare('ar',$this->ar);
$criteria->compare('fr',$this->fr);
$criteria->compare('image',$this->image,true);
$criteria->addCondition(' course_id not in ( select course_id from ict_cpackage where user_id='.$user_id.') ');
return new CActiveDataProvider($this, array(
'criteria'=>$criteria
));
}
...
?>
But return this error :
Undefined variable: data
1- Why return this error ?
2- how I can access to column value
Thanks in advance
'value' => "CHtml::link('Add',array('packages/add','user_id'=>$user_id,'course_id'=>\$data->course_id))",
You are using "" to quote your string, so you need to escape the $ on $data, so it reads as \$data.

Categories