How to convert model data objects array to dataProvider - php

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

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

Accessing value of indirectly related models

I am displaying a CGridView below CDetailView on view.php page for Company model. I have problem in displaying values in CGridView using company details. The company model has an array of CompanyAddresses which is used as CArrayDataProvider for CGridView.
$config = array();
$dataProvider = new CArrayDataProvider($rawData=$model->companyAddresses,$config);
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider
, 'columns'=>array(
//'id',
array('header'=>'SN.',
//'value'=>'++$row', // may nt work with pagination but the below does work
'value'=>'$this->grid->dataProvider->pagination->currentPage * $this->grid->dataProvider->pagination->pageSize + ($row+1)',
),
'address',
array(
'name'=>'Tehsil',
//'value'=> Utility::getTehsilName(Tehsil::model()->findByPk('tehsil_id')),
'value'=> Utility::getTehsilName($this->loadModel('tehsil_id')),
//'value'=> Tehsil::model()->findByAttributes( array('id' => 'tehsil_id' ) )->name,
),
array(
'name'=>'address_tag_id',
'value'=>AddressTag::model()->findByPk('address_tag_id'),
),
)
));
I am not able to fetch Tehsil_Name from Tehsil Table which has its ID inside CompanyAddress table.
Your using value attribute is wrong, check this:
'value'=>function($data){
return Utility::getTehsilName($data->tehsil_id);
},
value is a php expression that is evaluated to produce the contents of the gridview cell as below
'value' => 'Utility::getTehsilName($this->grid->controller->loadModel($data->tehsil_id))'
If you had used relation chaining to solve this your expression would have been simplified to say:
'value' => '$data->model1->tehsil->name'
where model1 is the middle relation.

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

Data isn't displaying from another table in CGridView Widget

I have two table Event and EventCategory. I am using zii.widgets.grid.CGridView widget to display all the events in the admin section.
I have created the following relations between tables.
Relation in EventCategory model:
'event' => array(self::HAS_MANY, 'Event', 'category_id'),
Relation in Event model:
'category' => array(self::BELONGS_TO, 'EventCategory', 'category_id'),
The following code I am using to display the Events:
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'event-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'summaryText'=> '',
'columns'=>array(
array('header'=>'Id','name'=>'event_id','filter'=>''),
'event_code',
'category.evntcatm_name',
'event_name',
array(
'class'=>'CButtonColumn',
'htmlOptions'=>array('class'=>'actions aligncenter'),
'deleteButtonImageUrl'=>false,
'updateButtonImageUrl'=>false,
'viewButtonImageUrl'=>false
),
),
)); ?>
'category.evntcatm_name' doesn't display anything. It is just creating the blank column with NO ERROR. What I am missing here.
Please try something like it
$data->category->evntcatm_name
You should use code like this:
'columns' = array(
/*YOUR DATA*/
array(
'name' => 'category_id',
'value' => function($data) {
return !empty($data->category) ? $data->category->evntcatm_name : null;
}),
)
This way can solve your problem with "Trying to get property of non-object". If you see blank cell in grid that means you miss relation (or it doesnt exist, in this way you should check relation condition or database)
Here is a few wild guesses:
Is category.evntcatm_name correctly spelled?
Is there actually data in the evntcatm_name field to begin with?
I know it might sound too simple to miss, but the error almost has to be on that level.
Try finding a category using the primary key and output it's evntcatm_name.
$cat = EventCategory::model()->findByPk(1);
echo $cat->evntcatm_name;
Maybe if you could share your schema for those two tables?
You can use
array(
'header' => 'Category Title',
'value' => '$data->category->evntcatm_name'
),
instead of 'category.evntcatm_name'
The model instance is not object now in the Cgidview:
Try
$data['category']['evntcatm_name'];

Searching criteria in Mongo db documents with Yii

How can I create a search form/criteria for "one-to many" relations: let's say "select all teams with crowd > 10.000".
I'm using MongoRecord extension (http://www.yiiframework.com/extension/mongorecord/) as a basic active record for MongoDb.
I created a GridView with Yii based on a collection from a mongo db (it works for me).
One of my document`s collection has a structure like this:
{
_id":1,
"teamId":2453,
"teamName":"Team A",
"competition":["Competition A","Competition B"],
"matches":
[
{
"_id":147852,
"crowd":10234,
"yellowCards":2,
"scorers" [{....}]
....
}
]
...
}
My documents:
$teams = MongoTeam::model()->findAll();
My dataProvider is:
$dataProvider=new CArrayDataProvider($teams, array(
'id'=>'_id',
'sort'=>array(
'attributes'=>array(
'_id', 'teamId', 'teamName', 'matches', ...
),
),
'pagination'=>array(
'pageSize'=>20,
),
));
$this->render('index', array('dataProvider'=>$dataProvider));
And in the view I have something like this:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'columns'=>array(
array(
'name' => 'Team ID',
'type' => 'raw',
'value' => 'CHtml::encode($data->teamID)'
),
array(
'name' => 'Team Name',
'type' => 'raw',
'value' => 'CHtml::encode($data->teamName)'
),
...
But I'm not able to create filters with criteria for subdocuments (my case: "matches"). I don't want to use any other mongoDB extension/module etc.
Thanks and sorry for my bad english.
$query=array(
'matches.crowd'=>array('$gt'=>10000),
'matches.$'=>1
);
$teams = MongoTeam::model()->findAll($query);
You can use like this. But you must not use a data provider like that. Because it will generate too much rows into the $teams var. You must use criteria for data providers. I am doing that with YiiMongoDbSuite it has EMongoCriteria and EMongoDataProvider classes to accomplish that.

Categories