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',
));
Related
I have the registered Comment model which has a User reference, like this:
public function user() {
return $this->belongsTo('App\User');
}
This function returns an instance of a User, and that's correct, but I don't know how to register the User column the get que user property using Backpack. Instead, I'm get a JSON representation of my model:
So, how do I get a specific field from my relationship function?
Sounds like the select column is a perfect match for you. Just use it in your EntityCrudController's setup() method, like so:
$this->crud->addColumn([
// 1-n relationship
'label' => "User", // Table column heading
'type' => "select",
'name' => 'user_id', // the column that contains the ID of that connected entity;
'entity' => 'user', // the method that defines the relationship in your Model
'attribute' => "user", // foreign key attribute that is shown to user
'model' => "App\Models\User", // foreign key model
]);
The "attribute" tells CRUD what to show in the table cell (the name, the id, etc).
If you do:
$user = $comment->user->user;
You'll get 'test'; (from your example)
It may seem confusing because your User model has a user attribute. Maybe you can call it 'name' instead of 'user'. That way you'll call it:
$username = $comment->user->name;
Remember to check if the relationship exists before calling a property on the related model.
if(!is_null($comment->user)) {
$username = $comment->user->user;
}
Or:
$username = !is_null($comment->user) ? $comment->user->user : 'No user';
If you need to get some field from deeper relation, you can use closure column type:
$this->crud->addColumn([
'label' => trans('backend.column_names.agency_linked_service'),
'name' => 'agency_service_id',
'type' => 'closure',
'function' => function (AgencyLinkedServices $entry) {
return $entry->agencyService->agencyCategory->title;
}
]);
I have a table which has different types of text data from different sources, identified by type, lang, sourceId and stored in field text. Is there anyway to return by active record relation not object of table but only value of field text in oher words scalar query via relation?
Example: For now I have:
$modelName->RelationName->text) //field name storing expexted data, returns string.
Desired way is:
$modelName->RelationName//text field value returned only.
Yes But using lazy loading approach :
Update Your Relation as
public function getRelationName(){
//Related model Class Name
//related column name as select
return $this->hasOne(RelationClass::className() ,['id' => 'id'])->select('name')->scalar();
}
then get relation value as : -
$modelName->relationName//text field value returned only.
Extend your model with one or more getter for retrive the value you need using a relation eg:
In the model you need retrive the related data you can build a funtion for define the raltion (in this case an hasOne)
*/
public function getRelationName()
{
return $this->hasOne(ModelOfTheRelation::className(), ['column1' => 'column1', 'EvColumn2' => 'Evcolumn2']);
}
Then you can use getter function for the data
/* Getter f */
public function getRelatioName_field()
{
return $this->relationName->field;
}
In view you can easy obtain the data using
echo $model->relationName_field
or in gridview (dataprovider)
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'relationName_field',
this link could be useful http://www.yiiframework.com/wiki/621/filter-sort-by-calculated-related-fields-in-gridview-yii-2-0/
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.
I have Two diff tables as given below:
users and posts
Need data from user's table order by count of posts table
Relationship is defined as:
User Model:
public $hasMany = array('Post');
Post Model
Public $belongsTo = array('User');
counterCache - Cache your count()
This function helps you cache the count of related data. Instead of counting the records manually via find('count'), the model itself tracks any addition/deleting towards the associated $hasMany model and increases/decreases a dedicated integer field within the parent model table.
The name of the field consists of the singular model name followed by a underscore and the word “count”:
my_model_count
Let’s say you have a model called ImageComment and a model called Image, you would add a new INT-field to the image table and name it image_comment_count.
Once you have added the counter field you are good to go. Activate counter-cache in your association by adding a counterCache key and set the value to true:
<?php
class Image extends AppModel {
public $belongsTo = array(
'ImageAlbum' => array('counterCache' => true)
);
}
From now on, every time you add or remove a Image associated to ImageAlbum, the number within image_count is adjusted automatically.
You can also specify counterScope. It allows you to specify a simple condition which tells the model when to update (or when not to, depending on how you look at it) the counter value.
Using our Image model example, we can specify it like so:
<?php
class Image extends AppModel {
public $belongsTo = array(
'ImageAlbum' => array(
'counterCache' => true,
'counterScope' => array('Image.active' => 1) // only count if "Image" is active = 1
));
}
I have Cinema table & City table and I have relation with this tables by id.. and when I echo results i have PHP notice "Trying to get property of non-object"
What is the problem ? or I missed something ??
My Code:
Cinema model
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(
'countryCode' => array(self::BELONGS_TO, 'TblCountry', 'country_code'),
'city' => array(self::BELONGS_TO, 'TblCity', 'city_id'),
'tblCinemaMovies' => array(self::HAS_MANY, 'TblCinemaMovies', 'cinema_id'),
'tblDays' => array(self::HAS_MANY, 'TblDay', 'cinema_id'),
'tblShowtimes' => array(self::HAS_MANY, 'TblShowtime', 'cinema_id'),
);
}
City model
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(
'tblCinemas' => array(self::HAS_MANY, 'TblCinema', 'city_id'),
'countryCode' => array(self::BELONGS_TO, 'TblCountry', 'country_code'),
);
}
View file:
<?php echo $model->city_id->name; ?>
I recommend you to always check if the relation does not return null or an empty array.
The following code works well with HAS_ONE and BELONGS_TO relationship types:
$cinema = Cinema::model()->find(); // get a cinema instance, assuming there is at least one row in the database.
$city = $cinema->city; // get the relation
if ($city !== null) {
// $city is a valid model
} else {
// $city is null, the corresponding row does not exist in the database
}
You may also make this check without using a new variable (in this case, $city):
if ($cinema->city!==null) {
// the relation is available
}
Checking if the relation does not return null is the best way to avoid the PHP error "trying to get property of non-object". Also, if you are stuck with similar errors, it is recommended to use functions like var_dump() or, even better, a debugger.
Also, notice that array keys in the array returned from relations() function is the property that has to be accessed to get the relation model(s):
public function relations() {
return array(
'city' => array( ... ),
// city is the property that has to be accessed
// Yii's conventions recommend to use 'city_id' for the foreign key column name
);
}
Also note that it is good to follow Yii's conventions for naming relationships and columns to avoid using the same name for both a property and a relations - in this case, the relation will be unavailable and probably an error like "trying to access property of a non-object" will pop up when playing with the relation.
The last thing, when working with HAS_MANY or MANY_TO_MANY relationships, the relation returns an array of models even if there is only one model available and an empty array if there is nothing available.
Explanation in the docs:
http://www.yiiframework.com/doc/guide/1.1/en/database.arr#performing-relational-query
<?php echo $model->city->name; ?>
You must use $model->city to get the corresponding city of the $model.
Because the city_id is a array, in your view file, you should write the code like this
<?php echo $model->city_id[0]->name; ?>
That error happens when city_id is emptied or nulled (or the value doesn't exist in the foreign table).
If you're not sure that "city_id" exists, you can check it like this:
CHtml::value($model, 'city.name');
That way you always ensure that you'll not have an Exception when the value is empty or clear