In my model (let's say Model A) I have a field corresponding to the id of another model (Model B). In a CGridView composed of Model A items, instead of showing the id of Model B, I want to show another field of that model instance.
Here's how I am showing my CGridView;
$dataProvider = new CArrayDataProvider('Model A');
$dataProvider->setData($model_A_Data); // $model_A_data is an array of Model A Objects
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'data-id',
'dataProvider'=>$dataProvider, //$objects->search(),
'columns'=>array(
array('header'=>'Model A Id', 'name'=>'id'),
array('header'=>'Name', 'name'=>'name'),
array('header'=>'Date', 'name'=>'date_created'),
array('header'=>'Model B Id', 'name'=>'model_b_id'), // *HERE SHOW ANOTHER FIELD OF MODEL B*
),
));
How can I change that column in order to show another field of model B clasS?
Thanks
OK, I figured out how to solve this after discovering the $data var in CGridView which holds the corresponding row data.
Simply add this:
array('name'=>'Model B Another Field',
'value'=> 'ModelB::model()->FindByPk($data->id)->another_field'
),
say in Model A i have a relation
array('modelbrelationname','ModelB','id'),
So You can have the value like this
$dataProvider = new CArrayDataProvider('Model A');
$dataProvider->setData($model_A_Data); // $model_A_data is an array of Model A Objects
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'data-id',
'dataProvider'=>$dataProvider, //$objects->search(),
'columns'=>array(
array('header'=>'Model A Id', 'name'=>'id'),
array('header'=>'Name', 'name'=>'name'),
array('header'=>'Date', 'name'=>'date_created'),
array('header'=>'Model B Id', 'value'=>'modelbrelationname.id'), // *HERE SHOW ANOTHER FIELD OF MODEL B*
),
));
Related
I am having difficulty getting the filtering to work in CGridView for relational fields from another model.
URL Reference: Yii 1.1: Searching and sorting by related model in CGridView
I follow the codes and it seems to be returning me the inputs from the other model. Everything looks fine but unfortunately, the filter is not working.
On Search, it will display a quick load icon but failed to filter accordingly. Upon checking further, I noticed the input is wrong. I am using Google Inspect Element and noticed the following:
<input name="User[full_name]" type="text">
I am using User model, relational to Biodata. Shouldn't it be Biodata[full_name]? If this is, where should I be looking at the codes?
Thank you. :D
Filtering and sorting in CGridView widget can be done in few steps:
1. Add virtual field to your User model. It will be used to create column in CGridView; it also needed for proper filtering and sorting:
class User extends CActiveRecord
{
public $bioFullName;
//...
}
2. Modify search() function in your User model. You need to add array parameter to this function and add to $criteria object in this method connection with related model. To add sorting of related attribute, you also need to modify returned CActiveDataProvider. See what happens below:
public function search($params = array()) // <-- new parameter that handling params for searching
{
$criteria = new CDbCriteria($param);
$criteria->with = array('biodata'); //add relation with Biodata to $criteria object
// ... existing $criteria conditions
$criteria->addSearchCondition('biodata.full_name', $this->bioFullName, true, 'AND'); // add comparison of biodata.full_name
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
// ...
'sort'=>array(
'attributes'=>array(
'bioFullName'=>array( // <-- sorting of related field
'asc'=>'biodata.full_name ASC',
'desc'=>'biodata.full_name DESC',
),
'*',
),
),
));
}
3. Adjust CGridView widget in your view to show related column. In columns array of widget configuration add column named like virtual field from model (bioFullName):
<?php
$this->widget('zii.widgets.grid.CGridView', array(
// ... other widget configuration options
'columns'=>array(
// ... other columns
'bioFullName'=>array(
'name'=>'bioFullName', // <-- name of virtual model field
'value'=>'$data->biodata->full_name', // <-- getting field value from relation
'header'=>'Full name', // <-- CGridView column header
),
// ... other columns
),
));
?>
I have a relatively simple setup using Yii application but I'm struggling to access data across tables in the following scenario:
Two tables:
payments_info (id, data): where id is the primary auto increment key, model class name PaymentInfo
payments (id, payment_id, other_columns): here id is again a primary key and payment_id is foreign key pointing to one of the records in the payment_info table, model class name Payment
In the relations array inside the Payment model class I have the following:
'payment_id'=>array(self::BELONGS_TO, 'PaymentInfo', 'id'),
I haven't added anything in the PaymentInfo model's relations as technically it doesn't know anything about the other table.
I have a controller creating a CActiveDataProvider from the Payments model and showing all the records. In it, I'd like to have a field which would be showing the 'data' column from the PaymentInfo model but I have no idea how to get there.
In the cdbcriteria in the controller, used to create the data provider I tried using:
$criteria->with = array('payment_id');
And then in the view, inside the columns variable of the CGridView which displays the data provider I added:
array(
'name'=>'payment_id',
'visible'=>true,
'value'=> $data->payment_id->data,
),
I also tried different combinations of adding ' or " around the $data variable but with no success so far. I manage to get the correct payment_id displayed but I can't figure out how to display the 'data' value from the other table. Any tips appreciated!
you can use below method to Get Data From Another Relational Table in YII
Payment Model In Relation Function
public function relations()
{
return array(
'pinfos' => array(self::BELONGS_TO, 'PaymentInfo', 'payment_id'),
);
}
PaymentInfo Model In Relation Function
public function relations()
{
return array(
'payments' => array(self::HAS_MANY, 'Payment', 'payment_id'),
);
}
And In zii.widgets.grid.CGridView put this
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'post-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'pinfos.data',
/* other fields goes here*/
array(
'class'=>'CButtonColumn',
),
),
)); ?>
No need to do anything else.
My view lets the user see a person's details, including the families they are in. This is done in the DB with a Person table, Family table, and a familyMembership link table between the two.
The relationship in the CActiveRecord model for Person is as such:
'families' => array(self::MANY_MANY, 'Family', 'familymembership(Person, Family)'),
In my person controller, I am wanting to pass a variable into the view that has the related data in a way that TbGridView (CGridView but Bootstrap) will accept (a data provider). The controller calls the person model's getFamilies() function:
public function getFamilies() {
// returns an array of Family objects related to this Person model
$familiesArray = $this->getRelated('families');
// puts this array into a CArrayDataProvider
$families = new CArrayDataProvider($familiesArray);
return $families;
}
The return value goes back to the controller, which is then handed through in the renderPartial() call. The view has a TbGridView widget initialisation like this:
$this->widget('bootstrap.widgets.TbGridView',
array(
//the CArrayDataProvider from the model function
'dataProvider' => $families,
'columns' => array(
array(
'name' => 'Family Name',
// Example field from Family model
'value' => '$data->familyName'
)
)
));
However, in doing this I am getting the following error:
'Property "Family.id" is not defined. (D:\wamp\www\yii\framework\base\CComponent.php:130)'
The Family model does not have an id property, and I don't understand why the widget is looking for such.
What's going wrong here?
Thanks.
Quoting the doc from Yii Class Reference, you have to provide a keyField:
Elements in the raw data array may be either objects (e.g. model objects) or associative arrays (e.g. query results of DAO). Make sure to set the keyField property to the name of the field that uniquely identifies a data record or false if you do not have such a field.
By default keyField will be set to "id", so you need to overwrite it with your Family model primary key :
<?php
$familyDataProvider = new CArrayDataProvider($rawData, array(
'keyField' => 'yourPkNameHere',
));
I have two tables , one album and one photo. the photo table has a FK (album_id) which refer to id in album table.
now I want to show photos in CListview but I don't know how. :(
As I see it is uses dataProvider and I don't know how to combine relation with it.
would you help me?
Thank you masters.
It's simple
$dataProvider=new CActiveDataProvider('Photo', array(
'criteria'=>array(
'condition'=>'album_id=:album_id',
'params'=>['album_id'=>$album_id]
)
));
Then in view use this dataProvider:
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_photo'
));
First you should create the relation in you models.
In Album.php add sth like this:
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(
'photos'=>array(self::HAS_MANY, 'Photo',array('album_id'=>'id')),
);
}
Similar in Photo.php:
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(
'album'=>array(self::BELONGS_TO, 'Album',array('id'=>'album_id')),
);
}
Now you can use it in your code:
$dataProvider=new CActiveDataProvider('Photo', array(
'criteria'=>array(
'condition'=>'album_id='.$yourAlbumId,
)
));
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
...
));
If you need to refer to the Album in the CListview (let's say you have a field called "title" in the Album model), you can refer to it as $data->album->title in your items template.
I'm using Associations to Link Models together in CakePHP.
I have a Player model that is linked to a Statistic model using a $hasMany relationship. So basically one player can have many statistics.
After I set up these relationships, I use cake bake to generate the controllers and views for both the Player and Statistic models.
Everything works fine and works as expected, but when I go to add a statistic using the add template, the player_id is used as the association.
My question is how do I set up the model to use the player_id as the association but use something like the player's first and last name as the drop down menu in the add template.
Currently if I go to add a new statistic, I get a drop down box that called "Player" that lists all of the player id's but what I want is for the player's first_name and last_name to be in that drop down box instead of the id. I realize that I can modify the controller or template to accomplish this, but I Want to know if I can do this while setting up the model so that cake bake can take care of it.
Player Model:
<?php
class Player extends AppModel {
public $name = 'Player';
public $belongsTo = array(
'School' => array(
'className' => 'School',
'foreignKey' => 'school_id'
)
);
public $hasMany = 'Statistic';
}
Statistic Model:
<?php
class Statistic extends AppModel {
public $name = 'Statistic';
public $belongsTo = array(
'Player' => array(
'className' => 'Player',
'foreignKey' => 'player_id'
)
);
}
Players Table
`id|school_id|first_name|last_name|number|position
Cake uses the model's displayField attribute when choosing the default columns for a list. If none is defined for the model it will look for name or title. So in your model you can use:
public $displayField = 'first_name';
This will display the player's first name in the list.
If you want the display field to be the concatenation of two fields, you can use a virtual field in the model like so:
public $virtualFields = array(
'name' => "TRIM(CONCAT(Player.first_name, ' ', Player.last_name))"
);
Note the above works for Mysql. For another kind of database you will need to adjust the syntax. For example, for Sqlite it would be:
TRIM(Player.first_name || ' ' || Player.last_name)
Then add in your model:
public $displayField = 'name';