Attempt to read property "id" on null in Laravel 9 - php

Hello i got a problem my code is:
if($user->plan->id == 1) {
return view($this->activeTemplate . 'user.autopool', compact('pageTitle', 'commissions', 'deposit', 'transactions', 'commission', 'withdraw', 'transaction', 'username', 'balance', 'user', 'plans'));
} else {
return view($this->activeTemplate . 'user.nopool', compact('pageTitle', 'user'));
}
i want to get rid of this error from my code. i am stucking here.

$user->plan evaluates to null. You don't guard against this.
If you're using PHP8, you can use the nullsafe operator.
if ($user->plan?->id)
If you're using PHP7, you can use laravel's optional() function.
if (optional($user->plan)->id)
If the relationship between User and Plan is a belongsTo relationship (User belongsTo Plan), you might be better off just using the foreign key in the user model.
if ($user->plan_id)

Related

Evaluate existence of relationship as true or false - Laravel Relationships

I'm trying to create a policy like the following:
public function view(User $user, PersonalStatement $personalStatement)
{
return $user->applicant->id == $personalStatement->applicant_id || $user->mentor->exists();
}
I then test it with a User model where mentor relationship exists, but applicant relationship does not, and I get the error:
Trying to get property 'id' of non-object
I believe this is because the user->applicant returns null in this case.
What's the best way to evaluate if a model has a relationship where the response is either true or false?
Using exists() method returns null if the relationship does not exist.
To handle null case, you may use optional Laravel helper, it allows you to call any property/method even if your source is null, it returns null instead of throwing an exception.
public function view(User $user, PersonalStatement $personalStatement)
{
return optional($user->applicant)->id == $personalStatement->applicant_id || $user->mentor->exists();
}
To check the 'applicant" relationship of 'User' model, try
$user->applicant()->exists()
OR
$user->applicant()->count()
Note: Brackets after the relationship does really matter.

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.

Use accessor mutator's within Laravel 4 lists method

I have a simple mutator:
public function getFullnameAttribute($value)
{
return $this->first_name. ' ' .$this->last_name;
}
But I also have a method that returns a list of specific users for use in a select input:
static function getDeliveryManagers()
{
return User::IsDeliveryManager()->lists('first_name', 'id');
}
I need that array returned to be ['First Name Last Name', 'id']
But the mutator doesn't work, e.g.
return User::IsDeliveryManager()->lists('Fullname', 'id');
I found this: https://github.com/laravel/framework/issues/668
Which Taylor marks as being done but I cant get it working. Using Laravel 4.2.
Any help?
You need to call the lists() on Eloquent Collection. So make sure IsDeliveryManager() is returning correct values. Its better if you can share the code of IsDeliveryManager(). If its is query scope you need to call get() before lists().
return User::IsDeliveryManager()->get()->lists('fullname', 'id');
The mutator, even if it is in camelcase, should be called in lowercase.
So you should be calling it as such:
return User::IsDeliveryManager()->lists('fullname', 'id');

Laravel Check If Related Model Exists

I have an Eloquent model which has a related model:
public function option() {
return $this->hasOne('RepairOption', 'repair_item_id');
}
public function setOptionArrayAttribute($values)
{
$this->option->update($values);
}
When I create the model, it does not necessarily have a related model. When I update it, I might add an option, or not.
So I need to check if the related model exists, to either update it, or create it, respectively:
$model = RepairItem::find($id);
if (Input::has('option')) {
if (<related_model_exists>) {
$option = new RepairOption(Input::get('option'));
$option->repairItem()->associate($model);
$option->save();
$model->fill(Input::except('option');
} else {
$model->update(Input::all());
}
};
Where <related_model_exists> is the code I am looking for.
In php 7.2+ you can't use count on the relation object, so there's no one-fits-all method for all relations. Use query method instead as #tremby provided below:
$model->relation()->exists()
generic solution working on all the relation types (pre php 7.2):
if (count($model->relation))
{
// exists
}
This will work for every relation since dynamic properties return Model or Collection. Both implement ArrayAccess.
So it goes like this:
single relations: hasOne / belongsTo / morphTo / morphOne
// no related model
$model->relation; // null
count($model->relation); // 0 evaluates to false
// there is one
$model->relation; // Eloquent Model
count($model->relation); // 1 evaluates to true
to-many relations: hasMany / belongsToMany / morphMany / morphToMany / morphedByMany
// no related collection
$model->relation; // Collection with 0 items evaluates to true
count($model->relation); // 0 evaluates to false
// there are related models
$model->relation; // Collection with 1 or more items, evaluates to true as well
count($model->relation); // int > 0 that evaluates to true
A Relation object passes unknown method calls through to an Eloquent query Builder, which is set up to only select the related objects. That Builder in turn passes unknown method calls through to its underlying query Builder.
This means you can use the exists() or count() methods directly from a relation object:
$model->relation()->exists(); // bool: true if there is at least one row
$model->relation()->count(); // int: number of related rows
Note the parentheses after relation: ->relation() is a function call (getting the relation object), as opposed to ->relation which a magic property getter set up for you by Laravel (getting the related object/objects).
Using the count method on the relation object (that is, using the parentheses) will be much faster than doing $model->relation->count() or count($model->relation) (unless the relation has already been eager-loaded) since it runs a count query rather than pulling all of the data for any related objects from the database, just to count them. Likewise, using exists doesn't need to pull model data either.
Both exists() and count() work on all relation types I've tried, so at least belongsTo, hasOne, hasMany, and belongsToMany.
I prefer to use exists method:
RepairItem::find($id)->option()->exists()
to check if related model exists or not. It's working fine on Laravel 5.2
After Php 7.1, The accepted answer won't work for all types of relationships.
Because depending of type the relationship, Eloquent will return a Collection, a Model or Null. And in Php 7.1 count(null) will throw an error.
So, to check if the relation exist you can use:
For relationships single: For example hasOne and belongsTo
if(!is_null($model->relation)) {
....
}
For relationships multiple: For Example: hasMany and belongsToMany
if ($model->relation->isNotEmpty()) {
....
}
I use for single relationships: hasOne, belongsTo and morphs
if($model->relation){
....
}
Because if condition is null, this will be false.
For multiple relationships: hasMany, belongsToMany and morphs
if ($model->relation->isNotEmpty()) {
....
}
You can use the relationLoaded method on the model object. This saved my bacon so hopefully it helps someone else. I was given this suggestion when I asked the same question on Laracasts.
As Hemerson Varela already said in Php 7.1 count(null) will throw an error and hasOne returns null if no row exists. Since you have a hasOnerelation I would use the empty method to check:
$model = RepairItem::find($id);
if (!empty($temp = $request->input('option'))) {
$option = $model->option;
if(empty($option)){
$option = $model->option()->create();
}
$option->someAttribute = temp;
$option->save();
};
But this is superfluous. There is no need to check if the relation exists, to determine if you should do an update or a create call. Simply use the updateOrCreate method. This is equivalent to the above:
$model = RepairItem::find($id);
if (!empty($temp = $request->input('option'))) {
$model->option()
->updateOrCreate(['repair_item_id' => $model->id],
['option' => $temp]);
}
Not sure if this has changed in Laravel 5, but the accepted answer using count($data->$relation) didn't work for me, as the very act of accessing the relation property caused it to be loaded.
In the end, a straightforward isset($data->$relation) did the trick for me.
I had to completely refactor my code when I updated my PHP version to 7.2+ because of bad usage of the count($x) function. This is a real pain and its also extremely scary as there are hundreds usages, in different scenarios and there is no one rules fits all..
Rules I followed to refactor everything, examples:
$x = Auth::user()->posts->find(6); (check if user has a post id=6 using ->find())
[FAILS] if(count($x)) { return 'Found'; }
[GOOD] if($x) { return 'Found'; }
$x = Auth::user()->profile->departments; (check if profile has some departments, there can have many departments)
[FAILS] if(count($x)) { return 'Found'; }
[GOOD] if($x->count()) { return 'Found'; }
$x = Auth::user()->profile->get(); (check if user has a profile after using a ->get())
[FAILS] if(count($x)) { return 'Found'; }
[GOOD] if($x->count()) { return 'Found'; }
Hopes this can help, even 5 years after the question has been asked, this stackoverflow post has helped me a lot!
If you use the model class and use Eloquent ORM, then create a new method and return bool data. like
public function hasPosts(): bool
{
return $this->posts()->exists();
}
RelationLoaded method of Model class could be useful.
if ($this->relationLoaded('prices')) {
return;
}

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