Create filter for CGridView - php

I have a module, that have one Controller, one set of view, and 5 models(in future can be more).
So in controller i have action
$model = new $modelName('search');
$model->unsetAttributes();
$model->create_user_id = Yii::app()->user->id;
if (isset($_GET[$modelName]))
$model->attributes = $_GET[$modelName];
$this->render('model_view/adminModel', array(
'modelName' => $modelName,
'model' => $model,
));
and in view i have a widget based on CGridView
$this->widget('application.components.widgets.usertheme.UserGridView',
array(
'id'=>'user-grid',
'dataProvider' =>$model->search(),
'filter'=>$model,
'columns' => .....
.....
)
);
If i put in action action (line #3)
$model->create_user_id = Yii::app()->user->id;
it works fine, and show the data that are created by user that is on system now.
But if i want to find inforamtion from this table, but with the filter - created document by USER from another table (i have relation with it)
'document' => array(self::BELONGS_TO, 'Document', 'document_id'),
and in action write
$model->document->create_user_id = Yii::app()->user->id;
it doesnt work, and give error
Indirect modification of overloaded property Reports::$document has no effect

Related

How to sort the grid view in a modal popup without changing the url in YII2?

I have a gridview inside the modal popup. I tried to sort the grid view columns inside the model popup. i tried with Pjax but it changes the page url.
I want to sort gridview in the modal popup without changing the url.
Code:
<?php \yii\widgets\Pjax::begin();
echo GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'id' => 'data_lines_tables',
'columns' => [
[
'name',
'id'
]
]
]);
\yii\widgets\Pjax::end();?>
By default, Pjax will use pushState to update url, you should simply disable this by using :
\yii\widgets\Pjax::begin(['enablePushState' => false]);
Read more about Pjax widget.
Hi there are two ways to do sorting for Cgridview in Modal popup, I have tried in bootstrap modal popup.
Try using the CSort. Please remember, they keys in in $sort->attributes should match columns in the CGridView:
public function actionIndex(){
$sort = new CSort();
$sort->attributes = array(
'employee'=>array(
'asc'=>'employee.name',
'desc'=>'employee.name desc',
),
'company'=>array(
'asc'=>'company.company_name',
'desc'=>'company.company_name desc',
),
);
$dataProvider=new CActiveDataProvider('job', array(
'criteria'=>array('Criteria goes here'),
'sort'=>$sort,
));
$this->render('index',array(
'dataProvider'=>$dataProvider,
));
You can also use the sort like this, if u want to sort according to time or id whatever you choose according to your fields in database.
$dataProvider=new CActiveDataProvider('job', array(
'criteria'=>array('Criteria goes here'),
'sort'=>array(
'defaultOrder'=>'createTime DESC',
),
));

Pagination For Search Results using Yii

I have a search form, which returns a bunch of images. Because their number can be high, I would prefer having the results displayed using pagination. However, I cannot seem to get it to work properly. I have moved everything to the view to keep things as simple as possible.
Here is my code snippet for the search and pagination:
$searchData = $model->search(); // this is the result of the search
$pages = new CPagination($searchData->itemCount);
$searchData->setPagination($pages);
$pages->applyLimit($searchData->criteria);
$pages->pageSize = 2;
Then, I display the results using a "foreach" statement:
foreach($searchData->getData() as $data)
{
// results displayed here
}
Finally, I have the CLinkPager widget:
$this->widget('CLinkPager', array(
'pages' => $pages,
'header' => 'Отиди на страница: ',
'nextPageLabel' => 'Следваща',
'prevPageLabel' => 'Предишна',
)); `
The problem is: there is not a relation between the widget and the displayed results.
For instance, if I get 4 results, the widget correctly shows that there are 2 pages. However, the results are not displayed in two pages, all are shown in one and clicking the CLinkPager links does nothing.
I have done pagination in the past successfully before, but for all the data using
model()->findAll().
How do I state the relation between the pagination widget and the search results... ?
Thank you for your time.
I think you are possibly overcomplicating the process. You could more easily use CListView widget to display your results with pagination.
Your controller may have this;
public function actionIndex(){
$model = new Model;
$this->render('index', array('model' => $model);
}
Your model needs to have a search method that returns an instance of CActiveDataProvider, for example
public function search() {
$criteria = new CDbCriteria;
$criteria->compare('id', $this->id, true);
$criteria->compare('title', $this->title, true);
$criteria->order = 'sortOrder';
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
));
}
Then in your view file you can use this code;
$this->widget('widgets.CListView', array(
'dataProvider' => $model->search(),
'itemView' => '_list',
'template' => '{pager}{items}',
'pager' => array(
'nextPageLabel' => 'Следваща',
'prevPageLabel' => 'Предишна',
)
));
You can extend the CListView by putting this in your extensions folder, and change the page size there.
<?php
Yii::import('zii.widgets.CListView');
class CustomListView extends CListView {
public function init() {
if ($this->dataProvider !== null)
$this->dataProvider->pagination->pageSize = 30;
$this->dataProvider->pagination->nextPageLabel => 'Следваща';
$this->dataProvider->pagination->prevPageLabel => 'Предишна';
parent::init();
}
}
Then, use the CustomListView as follows:
<?php $this->widget('CustomListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_view',
)); ?>
You do not need to use CLinkPager widget directly this way.

Yii - Joins on tables are not working

I want to get the data from two tables. I have used the below code to do so. I am new to Yii, if I am doing it the wrong way, please suggest the right way.
Here is the code of controller:
$dataProvider=new CActiveDataProvider('Users', array(
'criteria'=>array(
'with'=>'leave',
'together'=>true,
'condition'=>'leave.user_id=:user_id',
'params'=>array(':user_id'=>$this->loadModel(Yii::app()->user->getId())->user_id),
),
));
$this->render('admin',array(
'dataProvider'=>$dataProvider,
));
Here is the code of view:
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'users-grid',
'dataProvider'=>$dataProvider,
'columns'=>array(
array(
'header' => 'Leave Type',
'name'=>'leave_type',
'value'=>'$data->leave->leave_type',
),
'employee_code',
'username',
'password',
array(
'class'=>'CButtonColumn',
),
),
));
My Problem is:
I am joining two tables User and Leave. I want to get the data of users from Leave table as well as the users table. the above code shows me data from user table, when i try to show data from Leave table it throws me following error:
Trying to get property of non-object
UPDATE
Here is my user model relations:
return array(
'leaves' => array(self::HAS_MANY, 'Leaves', 'leave_id'),
'creator' => array(self::BELONGS_TO, 'Users', 'created_by'),
'updator' => array(self::BELONGS_TO, 'Users', 'modified_by'),
'leave' => array(self::HAS_MANY, 'Leaves', 'user_id'),
);
Here is my leave model relations:
return array(
'user' => array(self::BELONGS_TO, 'Users', 'user_id'),
'creator' => array(self::BELONGS_TO, 'Users', 'created_by'),
'updator' => array(self::BELONGS_TO, 'Users', 'modified_by'),
);
You can't display leave relation, because it's a HAS_MANY, I mean, in your $data->leave you have an array of Leave objects.
You should implement implode function, for example:
'value'=> "implode(', ', array_map(function($object) { return $object->leave_type; },
$data->leave))"
BTW, leave relation i think should be a HAS_ONE instead of HAS_MANY, and in this case, you don't need in an implode function in GridView
'value'=>'$data->leave->leave_type', // WRONG
$data->leave = array of objects and you could not access directly leave_type from it. That array was returned from your below relation:
'leave' => array(self::HAS_MANY, 'Leaves', 'user_id'),
I'm not sure the leave type which you want to access and relate it with user. But in this case, the solution is you can add more relation to just access first leave record of user
'singleLeave' => array(self::HAS_ONE, 'Leaves', 'user_id'), // add this line on Model User
And then you can access it properly
'value'=>'$data->singleLeave->leave_type',
Actually, in the first approach, the $data->leave should populate array of Leaves and from there, each Leave record should have to go into child views, and this is the point where you have to go detail

YII CGridView. Trying to show attribute from other table. Relation not working

This is driving me nuts. I read many responses and tutorials and i can't pin point the problem here.
I have 2 Tables: tblEmpleado and tblProfesion Here is an image of the MySQL relations they have (Marked on red)
I want to display on a CGridView the attribute "Descripcion" from the table tblProfesion when displaying the data from tblEmpleado.
I tried using claveProfesion.descripcion without avail (It shows the INT number of the FK just fine without the ".descripcion" part). Also tried using something like:
array(
'header'=>'tableHeaderName',
'value'=>'(isset($data->claveProfesion)) ? $data->claveProfesion->descripcion : null', )
getting "Trying to get property of non-object".
Here is the Empleados.php relation part of the model code:
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(
'tblcelulars' => array(self::HAS_MANY, 'Tblcelular', 'claveEmpleado'),
'tblcuentabancos' => array(self::HAS_MANY, 'Tblcuentabanco', 'claveEmpleado'),
'idCentroTrabajo' => array(self::BELONGS_TO, 'Tblcentrotrabajo', 'idCentroTrabajo'),
'convenio' => array(self::BELONGS_TO, 'Tblconvenio', 'convenio'),
'claveProfesion' => array(self::BELONGS_TO, 'Tblprofesion', 'claveProfesion'),
);
}
And the CGridView part of the Admin.php View code
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'empleados-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'claveEmpleado',
'nombreEmpleado',
'idCentroTrabajo',
array(
'header'=>'tableHeaderName',
'value'=>'($data->claveProfesion!=null) ? $data->claveProfesion->descripcion : null',
),
'aniosExperiencia',
'telefono2',
'email',
...
array(
'class'=>'CButtonColumn',
),
),
)); ?>
And last, i don't know if its related but in the Model class "Profesiones.php" the relation is as follow:
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(
'tblempleados' => array(self::HAS_MANY, 'Tblempleado', 'claveProfesion'),
);
}
Could anyone help me out with this?
Your column and your relation both have the same name claveProfesion. As such Yii is returning the column instead of the relation when you call claveProfesion. To resolve it rename your relation to something else e.g claveProfesionObject
public function relations()
{
return array(
...
'claveProfesionObject' => array(self::BELONGS_TO, 'Tblprofesion', 'claveProfesion'),
);
}

How to convert model data objects array to dataProvider

Suppose I have model User which have many to many relation to itself named as friends.
so $user->friends (or $model->friends in view) gives me an array of User objects. I wanted to display the friends as gridview. But CGridView data as dataProvider object. Googling for it found the way to convert array of model objects to dataProvider object as given below.
$this->widget('zii.widgets.grid.CGridView', array(
'id' => 'gridUser',
'dataProvider' => new CArrayDataProvider($model->friends, array()),
));
Now using this I get an error
Property "User.id" is not defined.
UPDATE
public function relations()
{
return array(
'friends' => array(self::MANY_MANY, 'User', 'friendship(user_id, friend_id)'),
);
}
I use two stage building the provider shown below. But I found that it gives you trouble in terms of Pagination. I have not bothered to resolve that problem since am doing other things
$dataProvider = new CArrayDataProvider('User');
$dataProvider->setData($model->friends);
$this->widget('zii.widgets.grid.CGridView', array(
'id' => 'gridUser',
'dataProvider' =>$dataProvider,
));
That being said, your code should work (see the example below from API docs). I suspect there is wrong attribute in your relations than the provided code. Re-check the relation definition if it is ok
From Yii docs:
$rawData=Yii::app()->db->createCommand('SELECT * FROM tbl_user')->queryAll();
// or using: $rawData=User::model()->findAll(); <--this better represents your question
$dataProvider=new CArrayDataProvider($rawData, array(
'id'=>'user',
'sort'=>array(
'attributes'=>array(
'id', 'username', 'email',
),
),
'pagination'=>array(
'pageSize'=>10,
),
));
Got it :) , i can use CActiveDataProvider instead of CArrayDataProvider as given below
$this->widget('zii.widgets.grid.CGridView', array(
'id' => 'gridUser',
'dataProvider' => new CActiveDataProvider('User', array(
'data'=>$model->friends,
)),
//...... columns display list.....
));
Anyways thanks for the reply #Stefano

Categories