Yii Relations error Trying to get property of non-object - php

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

Related

Laravel Backpack - Show specific attribute from relationship function

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

Laravel 5.1 trying to get property of non object eloquent relationship, handle error

OrganizationsController.php
public function user_index()
{
if(!is_null(Organization::find(Auth::user()->player->organization)))
$organization = Organization::find(Auth::user()->player->organization->id);
else $organization=null;
return view('organizations.user_index', [ 'organization' => $organization ]);
}
To avoid "Trying to get property of non-object" when "player" have no "organization" I used this code. But it doesnt seem very nice. There is a better way to obtain this? Maybe im wrong but with this method there is a useless query, am I right?
Table Player: id, name
Table Organization: id, name, player_id
Assuming user hasOne player, and player hasOne organization, and these relationships are setup correctly, there is no need for either Organization::find() at all. The organization attribute is going to be the loaded Organization object already, so there is no need to re-find it.
public function user_index() {
// default to null
$organization = null;
// make sure there is an authenticated user and it has a player
if (Auth::user() && Auth::user()->player) {
// if the player has an organization, this will be the Organzation object
// if the player does not have an organization, this will be null
$organization = Auth::user()->player->organization;
}
return view('organizations.user_index', [ 'organization' => $organization ]);
}
Yes, for this check you might get one unnecessary SQL query executed. You can get rid of this if you do:
if(Organization::find(Auth::user()->player->organization_id)
instead of
if(!is_null(Organization::find(Auth::user()->player->organization)))
This way you check organization_id that is stored in player before trying to fetch organization from the database.

Yii2 - Gii Model Relations - Why is there a 0 after the function names?

I haven't seen this online when looking at other's code, guides, tutorials, etc.
When I generate a Model with Gii, the functions regarding relations all have a zero after them.
Example:
class Benefit extends \yii\db\ActiveRecord
{
// truncated Yii Model code...
public function getType0()
{
return $this->hasOne(BenefitTypes::className(), ['id' => 'type']);
}
}
BenefitTypes is an id to name mapping:
id | name
---------------
1 => Federal
2 => Non-Profit
In the 'benefit' table, it has column named 'type' that is a relation to the 'benefit_types' table 'id' column.
I though I should be able to do (in /views/benefit/index.php) 'type.name' but it doesn't work either. It changes the column name to "Type Name" and puts "(not set)" in the data table...
Example:
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'id',
'somevalue',
'type.name',
],
]) ?>
What is going on, why does it not act like it's supposed to?
UPDATE
I am beginning to think the 0 suffix to the relation function names, ie: getType0, is due to "type" being used in the table as a column name to avoid duplication or confusion. I can't find this documented though, so would like to have a definite answer on that.
I changed the function name to getTypeRelation(). Then in the index.php view, for the detailview widget, used 'typeRelation.name' and it returned the name through the relation just fine.
Your thinking is correct. Generation of the relation names is done by the function generateRelationName().
protected function generateRelationName($relations, $table, $key, $multiple)
{
if (!empty($key) && substr_compare($key, 'id', -2, 2, true) === 0 && strcasecmp($key, 'id')) {
$key = rtrim(substr($key, 0, -2), '_');
}
if ($multiple) {
$key = Inflector::pluralize($key);
}
$name = $rawName = Inflector::id2camel($key, '_');
$i = 0;
while (isset($table->columns[lcfirst($name)])) {
$name = $rawName . ($i++);
}
while (isset($relations[$table->fullName][$name])) {
$name = $rawName . ($i++);
}
return $name;
}
Yii uses the related table's name as the relation name. Should you have a column with the same name as the related table, a digit will be appended to the relation to avoid confusion due to Yii's handling of magic functions. This also occurs if you have two columns or more in a single table related to the same table e.g columns create_user_id, update_user_id and delete_user_id related to table user will result in relations named user, user0 and user1.
For your example, it is advisable to name your foreign key field something else e.g type_id or typeId. Yii will handle these correctly . The other alternative when you have multiple columns related to the same table is to just rename the functions.
Because relational column name and the relation name is same. When you call $benefit->type what you will expect, the value of the column/property type or the instance of BenefitTypes? So now you know. $benefit->type return the property value and $benefit->type0 returns the instance of relation.

how to display two models in one CGridView

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.

Yii: BELONGS_TO relation returns null if I change its name

I would like to know why the framework might have this strange behavior.
If I define the relation in my Event model as weird or any other name besides interest, it works properly getting an object of the class Interest.
public function relations()
{
return array_merge(
parent::relations(),
array(
'weird' => array(self::BELONGS_TO, 'Interest', 'interest_id'),
));
}
But if I change the name to interest it returns null
public function relations()
{
return array(
'interest' => array(self::BELONGS_TO, 'Interest', 'interest_id'),
);
}
So simply changing the name to interest means the relation will return null
Do you have any variables on the Event called interest you can't override native class variables with Yii specials like relations and magic methods. If not then something stranger is going on here.

Categories