Laravel - ERROR: Trying to get property 'depthead' of non-object - laravel

In my Laravel-5.8 blade that has this code:
#foreach($employees as $key => $employee)
<li class="list-group-item">
<b>Line Manager:</b>
#if(!$employee->linemanager)
<a class="float-right">N/A</a>
#else
<a class="float-right">{{ $employee->linemanager->fullName() ?? 'None' }}</a>
#endif
</li>
<li class="list-group-item">
<b>HOD:</b>
#if(!$employee->department->depthead)
<a class="float-right">N/A</a>
#else
<a class="float-right">{{isset($employee->department->depthead) ? $employee->department->depthead->first_name. ' ' .$employee->department->depthead->last_name : 'None'}}</a>
#endif
</li>
#endforeach
and its pointing to this line:
#if(!$employee->department->depthead)
How do I resolve it?
Thanks

The root cause of your issue is that $employee->department is either null or not an Object (Instance of Department, assuming you have Model and Relationships setup properly). You've got a check in place, but it's in the wrong spot. Check for $employee->department and $employee->department->depthead:
#if($employee->department)
#if($employee->department->depthead)
{{ $employee->department->depthead->first_name. ' ' .$employee->department->depthead->last_name }}
#else
None
#endif
#else
N/A
#endif
The defaults returned from a properly formed relationship will remove the need for string checks, meaning that #if($employee->department) and #if($employee->department->depthead) will be "truthy" or "falsey" enough to handle your use case.
Sidenote, this complexity is best moved to a Model function. In your Employee model, add this function:
public function getDepartmentHeadAttribute(){
if ($this->department) {
if ($this->department->depthead) {
return "{$this->department->depthead->first_name} {$this->department->depthead->last_name}";
} else {
return 'None';
}
} else {
return 'N/A';
}
}
Then, in your .blade.php file, you can simply do:
#foreach($employees as $employee)
{{ $employee->department_head }}
#endforeach
And it will perform the required if checks inside your Model and output First/Last, None or N/A as requird.

#if(!$employee->department->depthead)
look like the employee->department is not null, but it is not an object too ...
may be it is a string or number ....
#if(!$employee->department->depthead)
you could use 'is_object' method to determine that ...
#if( is_object($employee->department))
#if(!$employee->department->depthead)
....
#endIf
#endIf
but i don't think that the problem ...
the problem maybe you miss loading the relation,
if the property 'department' is a field of type 'json'
don't forget to cast it in model to 'array'

Related

Laravel calling controller function from blade file not working

I have a Laravel project where I'm trying to call a controller function from blade file called nav.blade.php, but I'm getting following error:
syntax error, unexpected fully qualified name
"\App\Http\Controllers\ProductC...", expecting ":".
nav.blade.php
{{ use \App\Http\Controllers\ProductController; }}
<div class="container">
<ul class="navbar-nav mr-auto">
{{ $is_admin = ProductController::isAdmin(); }}
#if($is_admin == "admin")
<li class="nav-item">
<a class="nav-link" href="/posts">Admin</a>
</li>
#endif
</ul>
</div>
ProductsController.php
public static function isAdmin()
{
$user_id = Auth::id();
$user = User::findOrFail($user_id);
$is_admin = $user->role;
if($is_admin==="admin"){
return "admin";
}elseif($is_admin==="moderator"){
return "moderator";
}else{
return "user";
}
}
You access the static controller function from the blade template.
<?php
$isAdmin= App\Http\Controllers\ProductController::isAdmin();
?>
{{ }} are used to echo anything you want. If you want to import a class, one solution is to do like the following:
<?php
use \App\Http\Controllers\ProductController;
$is_admin = ProductController::isAdmin();
?>
<div class="container">
<ul class="navbar-nav mr-auto">
#if($is_admin == "admin")
<li class="nav-item">
<a class="nav-link" href="/posts">Admin</a>
</li>
#endif
</ul>
</div>
But this isn't a best practice I recommend you to move isAdmin() method from ProductController and set it as global function of your system so you can directly access it from your view without importing a controller.
Never EVER use a controller in a Blade. That is not good in any way and would require me a lot of explanation that is already in some blogs...
A controller is ONLY used for accessing something through a URL, do something and done, it is not a Service class where you do business logic anywhere you want.
So, move that method to a Service class (do not confuse with Service Provider) and use it in the blade. It would still be better to pass that variable to the view and not using any class just for that...

Trying to call the relationship of imageable_type in polymorphic model

So I have images that are stored by a particular model each time they recorded (i.e. Thread, Reply, Comment).
I want to call to be able to call these values to get the path where the images originate from.
So far I have this code:
In each of the models (Thread, Reply, Comment):
public function images()
{
return $this->morphMany(Image::class, 'imageable');
}
In the Image Model:
public function image()
{
return $this->morphTo();
}
In the view (I can't figure out how to call the related model here)
<div class="image-show">
Found here:
#if ($image->imageable_type == 'App\Thread')
<a href="/forums/{{ $image->image->channel->slug }}/{{ $image->image->slug }}/">
{{ $image->image->title }}
</a>
#endif
#if ($image->imageable_type == 'App\Reply')
<a href="">
{{ dd($image->image()->path()) }}
</a>
#endif
#if ($image->imageable_type == 'App\ProfilePost')
<a href="{{ $image->path() }}">{{ $image->image->user->name }}'s profile
</a>
#endif
#if ($image->imageable_type == 'App\ProfilePostComment')
#endif
#if ($image->imageable_type == 'App\Product')
#endif
#if ($image->imageable_type == 'App\Review')
#endif
#if ($image->imageable_type == 'App\ReviewComment')
#endif
#if ($image->imageable_type == 'App\Thread')
#endif
#if ($image->imageable_type == 'App\ProductComment')
#endif
<img src="{{ $image->path }}">
</div>
Can anyone help show me how I can call the imageable_type relationship to retrieve the Models attributes and use them accordingly? Thank you!
Following the conventions the relationship definition in the Image model should be
//-----------------------------Option 1------------------------
public function imageable()
{
return $this->morphTo();
}
//Access the related like
$image->imageable
//-----------------------------Option 2------------------------
//OR if you want to keep it as image, specify type & id columns
public function image()
{
return $this->morphTo('image', 'imageable_type', 'imageable_id');
}
//Access the related like
$image->image

I can't retrieve data from the related table(model) in Laravel6

I can't retrieve data from the related table.
There are 3 models(tables).
User
Chirp (has 'user_id' as foreign key)
Click (has 'chirp_id' as foreign key)
then I want to retrieve User & Click's data from Chirp model.
So I wrote:
Chirp.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Chirp extends Model
{
public $timestamps = false;
protected $guarded = [];
public function user()
{
return $this->belongsTo('App\User');
}
public function clicks()
{
return $this->hasMany('App\Click');
}
}
HomeController.php
class HomeController extends Controller
{
public function index()
{
$chirps = Chirp::with(['user','clicks'])
->orderBy('posted_at', 'desc')
->get();
return view('home', ['chirps' => $chirps]);
}
}
home.blade.php
#foreach($chirps as $chirp)
<div>
<div>by
<b>{{ $chirp->user->name }}</b>
on
<small>{{ $chirp->posted_at }}</small>
</div>
<div>
<p>{{ $chirp->text }}</p>
<p>{{ $chirp->click->ip_address }}</p>
</div>
</div>
#endforeach
at home.blade.php, {{ $chirp->click->ip_address }} can't be retrieved and get error "Facade\Ignition\Exceptions\ViewException Trying to get property 'ip_address' of non-object"
However, if I delete it, I can retrieve {{ $chirp->user->name }} properly.
Why can't I retrieve Click model from Chirp model, While I can retrieve User model from Chirp model?
Thank you.
You need to loop over your clicks as well:
#foreach($chirps as $chirp)
<div>
<div>by
<b>{{ $chirp->user->name }}</b>
on
<small>{{ $chirp->posted_at }}</small>
</div>
#foreach($chirp->clicks as $click)
<div>
<p>{{ $chirp->text }}</p>
<p>{{ $click->ip_address }}</p>
</div>
#endforeach
</div>
#endforeach
Chirp has many clicks (not click). You have to foreach $chirp->clicks in your blade.
#foreach ($chirp->clicks as $click)
<p>This is click id {{ $click->id }}</p>
#endforeach
You've hasMany relation with Chirp and clicks
And here you're getting many clicks instead of click
#foreach($chirp->clicks as $click)
<p>{{ $click->ip_address }}</p>
#endforeach
To debug this problem you can take the following steps:
Check if the chirps variable has any data within the controller.
dd($chirps);
If you know you have the data you can take the steps to make your blade better.
Becasue its a many to many relation you should loop trough the data.
#foreach($chirps as $chirp)
#foreach($chirp->clicks as $click)
<div>
<p>{{ $chirp->text }}</p>
<p>{{ $click->ip_address }}</p>
</div>
#endforeach
#endforeach

isset is not working in laravel

I am sending a variable from controller to a view.
$message = "Thanks for Contacting";
return redirect('services')->with($message);
HTML
#isset ($message)
<a style="color: red;"> {{$message}} </a>
#endisset
But it shows en error, because when the first services is loaded from this route
Route::get('/services', function () {
return view('services');
});
There's no variable,so it gives en error. Please let me know what I am missing?
The problem is how you're passing the variable to your view.
the correct way is:
return view('services')->with('message', $message);
or
return view('services')->withMessage($message);
or
return view('services', ['message' => $message]);
or
return view('services', compact('message'));
You have to use it with #if,
Try this:
#if(session()->has('message'))
<a style="color: red;"> {{ session('message')}} </a>
#endif
and also change your controller like this:
return redirect('services')->with('message', $message);
The variable that set in redirect()->with() will saved to sessions variable, so to access it just call session() helper. Example:
#if (session('message'))
<div class="alert alert-success">
{{ session('message') }}
</div>
#endif
More explanation:
https://laravel.com/docs/5.6/redirects#redirecting-with-flashed-session-data

How to show comments and replycomments in laravel

I don't know how to show comments and replycomments in my post page. My comments table contains id, sender_id, replyer_id, reply_id, comment_text.
CommentController returns a comment object. In Post.blade.php, how do I write a foreach loop or loops?
Your Controller code must be similar to this:
public function index()
{
$comments = Comment::with(['sender', 'other-relation'])->get();
return view('comments.index', compact('comments'));
}
and your blade code must be similar to this:
<ul>
#foreach($comments as $comment)
<li>{{ $comment->comment_text }}</li>
#if ($comment->sender) // or other relation
<a> {{$comment->sender->name}}<a> // relation name and column name must be fix yourself
#endif
#endforeach
</ul>
Inside blade file:
<ul>
#foreach($comments as $comment)
<li>{{ $comment->comment_text }}</li>
#endforeach
</ul>

Resources