how to display two models in one CGridView - php

I have two tables, 1. Students 2.SrkParents.
relations in Students model is,
'srkParents' => array(self::HAS_MANY, 'SrkParents', 'studentID'),
relations in SrkParents model is,
'student' => array(self::BELONGS_TO, 'Students', 'studentID'),
view is,
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'students-grid',
'dataProvider'=>$dataProvider,
'filter'=>$model,
'columns'=>array('studentID','status','del',
array('name'=>'SrkParents.fathers_name',
'value'=>'$data->Students->fathers_name',
'type'=>'raw'),
array('class'=>'CButtonColumn',),),));
I dont know where i did mistake.. I get the error as shown below,
Property "Students.Students" is not defined.

Modified Answer: Just change the relation has_one from has_many
'srkParents' => array(self::HAS_ONE, 'SrkParents', 'studentID'),

Your relation srkParents is a HAS_MANY relation. Thus $data->srkParents is an array of SrkParents and not an object. Which makes sense, because your students have several parents.
I don't know enough about your model attributes, so i can only guess: One way to solve this would be to add a geter to your Students model which loops over $this->srkParents to find the father object and return the name from there:
public function getFatherName()
{
foreach($this->srkParents as $parent)
if($parent->sex=='m' /* just guessing */)
return $parent->name;
}
Then you could use $data->fatherName in your grid view.

Your relation name is student and this is case sensetive.
Try to change $data->Students->fathers_name to $data->student->fathers_name.
Property Students.Students is not defined.
What am I doing wrong?
you trying to get field Students from model Students which is not defined.

Related

How to define relation through another relation in Laravel like via() in Yii2?

I need to define one relation through another relation in Laravel so both relations can be eagerly loaded in the optimal way.
For example I have item and attr tables with attr_item intermediate table. In Yii2 I can define one relation through another by using method via:
class Item extends ActiveRecord
{
public function getAttrItems()
{
return $this->hasMany(AttrItem::class, ['item_id' => 'id']);
}
public function getAttrs()
{
return $this-hasMany(Attr::class, ['id' => 'attr_id'])->via('attrItems');
}
}
So when I call $item = Item::find()->with('attrs')->where(['id' => 1])->one() Yii2 makes two additional queries: to table attr_item with condition item_id = 1 and to table attr with identifiers found in previous query. Something like:
SELECT * FROM "item" WHERE "id"=1
SELECT * FROM "attr_item" WHERE "item_id"=1
SELECT * FROM "attr" WHERE "id" IN (1, 2, 3)
After that I have two populated relations: $item->attrs and $item->attrItems.
But I didn't found the same functionality in Laravel. I can define $this->hasManyThrough(Attr::class, AttrItem::class, 'item_id', 'id', 'id', 'attr_id') or $this->belongsToMany(Attr::class, 'attr_item', 'item_id', 'attr_id', 'id', 'id') in Item class but it makes just one query to DB like:
select
"attr".*,
"attr_item"."item_id" as "pivot_item_id",
"attr_item"."attr_id" as "pivot_attr_id"
from
"attr"
inner join "attr_item" on "attr"."id" = "attr_item"."attr_id"
where
"attr_item"."item_id" = '1';
And of course it doesn't hydrate attrItems relation because there is no information about intermediate relation. I can eagerly load both relations attrs and attrItems but in this case the intermediate table attr_item will be used twice and that is not good for performance.
Im not quite sure if this is what you mean but have you looked at 'nested eager loading morph to relationships'?
https://laravel.com/docs/master/eloquent-relationships#eager-loading
Scroll down a bit for 'nested eager loading morph to relationships'.

Add field to an Eloquent model

So I have two Laravel/Eloquent models, and I want to add one more field to one of them.
Model 'Car' gets data from table 'cars' and has fields 'id', 'model', 'color' and 'price'. Model 'Person' has fields 'id', 'name' and 'car_id', which is foreign key from 'cars' table. I want model 'Person' to have a field named 'car', which would contain car model from 'Car' model, depending on existing car_id. I've tried something like:
use App\Models\Car;
class Person extends Model {
protected $car = array(Car::find($this->car_id));
}
But that was unsuccessful (errors like 'syntax error, unexpected '(', expecting ')''). What could be the solution? Thanks!
You need to define One-To-Many relationship first. Then get car model for the person:
$carModel = Person::find($personId)->car->model;
Take a look at Eloquent Relationships. What you are trying to do is to create a relationship between Car and Person models. It is up to you if a person can own one or multiple cars. I am suggesting you to let a person have multiple cars.
So, the Person model should know that it has multiple cars:
class Person extends Model
{
public function cars()
{
return $this->hasMany(App\Car::class);
}
}
A car belongs to a person, so the model should know that:
class Car extends Model
{
public function person()
{
return $this->belongsTo(App\Person::class);
}
}
Of course, when creating the tables you should add the field person_id to the CARS table.
Well, what I needed was:
protected $appends = ['car'];
public function getTypeAttribute($car)
{
return Car::find($this->car_id)->model;
}
It was all about serialization and 'protected $appends', thank you all :)
That's not how its done.
The person can have a car (or many). Let's suppose that every person have one car in your database, your car table should have a nullable person_id column, and add this to your User model
public function car() {
return $this->hasOne('App\Role');
}
Now you can get the person and the his car information's like this
User::where('id',$id)->with('car')->get();
I hope you get the point here

CActiveDataProvider using relations accessing foreign key data from another table

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.

fetch photos of an album in Yii (relation case)

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.

Yii Relations error Trying to get property of non-object

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

Categories