Trying to get property of non-object after passing an array - php

I have a users table and a photos table. The photos table has been linked to the users table (and some other tables) through imageable_id and imageable_type. Everything's working fine for that.
Now I wanted to return an array to a view that contains: user's name, user's email, user's desc, and user's image path (which is from the photos table).
What I did was I created an array that holds a collection of arrays from each user's data, and then passed that array to the view:
$user_admins = array();
$admin_id = 1;
$admins = User::where('role_id', $admin_id)->orderBy('name', 'asc')->get();
foreach($admins as $admin)
{
$photo = Photo::where('imageable_id', $admin->id)->where('imageable_type', 'App\User')->first();
$admin_data = array('name'=>$admin->name, 'email'=>$admin->email, 'desc'=>$admin->desc, 'path'=>$photo->path);
array_push($user_admins, $admin_data);
}
// return $user_admins;
//Return View
return view('pages/home_admin', compact('user_admins'));
However on the view page, I get a Trying to get property of non-object that points out to my:
<h5 class="card-title">{!!$admin->name!!}</h5>
How can I access those user's data on my view?
Thanks a lot!
Update
I also tried:
foreach($admins as $admin)
{
$admin_data['name'] = $admin['name'];
$admin_data['email'] = $admin['email'];
$admin_data['desc'] = $admin['desc'];
$photo = Photo::where('imageable_id', $admin->id)->where('imageable_type', 'App\User')->first();
$admin_data['path'] = $photo['path'];
// $admin_data = array('name'=>$admin->name, 'email'=>$admin->email, 'desc'=>$admin->desc, 'path'=>$photo->path);
array_push($user_admins, $admin_data);
}
// return $user_admins;
//Return View
return view('pages/home_admin', compact('user_admins'));
Still got the same error :<
View's code:
#foreach ($user_admins as $admin)
<div class="card text-center shadow-sm ml-3" style="width: 18rem;">
<div class="card-body">
<img src="../user_images/img_defaultprofile.png" class="mb-3" style="height: 10vh;" alt="" srcset="">
<h5 class="card-title">{!!$admin->name!!}</h5>
<h6 class="card-subtitle mb-2 text-muted">{!!$admin->email!!}<h6>
<p class="card-text">{!!$admin->desc!!}</p>
View Profile
</div>
</div>
#endforeach

You can handle it by defining relationship between user and photo, On your user model define a relationship with photo model
public function photo()
{
return $this->hasOne('App\Photo','imageable_id');
}
Then on your controller
$user_admins = User::where('role_id', $admin_id)->orderBy('name', 'asc')->get();
return view('pages/home_admin', compact('user_admins'));
As the relationship has been defined on user model you can retrieve the photo and user data as follows on view
#foreach ($user_admins as $admin)
<div class="card text-center shadow-sm ml-3" style="width: 18rem;">
<div class="card-body">
<img src="{!!$admin->photo->path!!}" class="mb-3" style="height: 10vh;" alt="" srcset="">
<h5 class="card-title">{!!$admin->name!!}</h5>
<h6 class="card-subtitle mb-2 text-muted">{!!$admin->email!!}<h6>
<p class="card-text">{!!$admin->desc!!}</p>
View Profile
</div>
</div>
#endforeach

So the error message is saying Trying to get property of non-object. That means, you are trying to access property of a variable which is not an object but something else. You are getting this error because, the variable you are passing $user_admins is an array but you are trying to access it as an object.
How to access an array? This should be the your code in view:
#foreach ($user_admins as $admin)
<div class="card text-center shadow-sm ml-3" style="width: 18rem;">
<div class="card-body">
<img src="../user_images/img_defaultprofile.png" class="mb-3" style="height: 10vh;" alt="" srcset="">
<h5 class="card-title">{!!$admin['name']!!}</h5>
<h6 class="card-subtitle mb-2 text-muted">{!!$admin['email']!!}<h6>
<p class="card-text">{!!$admin['desc']!!}</p>
View Profile
</div>
</div>
#endforeach

Related

How to get two ids in one route using Laravel?

Here are my routes:
Route::get('/admin/job-seeker/search/employer/{employerId}', 'AdminJobSeekerSearchController#show')->name('admin.job-seeker.search.employer.show')->middleware('verified');
Route::get('/admin/job-seeker/search/employer/{employerId}/post-a-job/{jobPostId}', 'AdminEmployerJobPostsController#show')->name('admin.employer.post-a-job.show')->middleware('verified');
Controller for first Route:
public function show($employerId)
{
$user = Auth::user();
$jobSeekerProfile = JobSeekerProfile::all()->where('user_id', $user->id)->first();
$employerProfiles = EmployerProfile::limit(1)->where('id', $employerId)->get();
$jobPosts = JobPosts::all();
return view('admin.job-seeker.search.employer.show', compact('employerProfiles', 'id', 'jobSeekerProfile', 'jobPosts'));
}
Controller for second route:
public function show($employerId, $jobPostId)
{
$user = Auth::user();
$jobSeekerProfile = JobSeekerProfile::all()->where('user_id', $user->id)->first();
$employerProfiles = EmployerProfile::limit(1)->where('id', $employerId)->get();
$jobPosts = JobPosts::all();
$jobPost = JobPosts::findOrFail($jobPostId);
return view('admin.employer.post-a-job.show', compact('jobSeekerProfile', 'employerProfiles', 'jobPosts', 'jobPost'));
}
I have two tables employer_profiles and job_posts. After an Employer Registers and creates a profile, he can create job posts with 2 fields job_title and job_description. For example it could be Project Manager and then a description for this role.
I'm getting this error:
Missing required parameters for [Route:
admin.employer.post-a-job.show] [URI:
admin/job-seeker/search/employer/{employerId}/post-a-job/{jobPostId}].
(View:
C:\xampp\htdocs\highrjobs\resources\views\includes\job_seeker_search_employers.blade.php)
(View:
C:\xampp\htdocs\highrjobs\resources\views\includes\job_seeker_search_employers.blade.php)
job_seeker_search_employees.blade:
#if($employerProfiles)
#foreach($employerProfiles as $employerProfile)
<br><br>
<div class="col-md-6 offset-md-3">
<div class="card" style="width: 28rem;">
<img class="card-img-top" src="https://via.placeholder.com/400" alt="Card image cap" style="max-height:400px;">
<div class="card-body">
<h1 class="card-title text-uppercase" style="color: #5dad07;"><strong>{{ $employerProfile['immediate_contact'] }}</strong></h1>
<h3><strong>Positions Available:</strong><br>
#if($jobPosts->where('user_id', $employerProfile->user_id)->count() > 0)
#foreach($jobPosts->where('user_id', $employerProfile->user_id) as $jobPost)
<h5>{{ $jobPost['job_title'] }}</h5>
#endforeach
#else
<h5>No Positions Available</h5>
#endif
</h3>
<h3><strong>Contact Details:</strong></h3>
<p>
<strong>Company Name:</strong> {{ $employerProfile['company_name'] }}<br>
<strong>Contact Email:</strong> {{ $employerProfile['email'] }}<br>
<strong>Phone:</strong> {{ $employerProfile['company_phone'] }}
</p>
<strong>Address:</strong>
<address>{{ $employerProfile['company_address'] }}</address>
</div>
</div>
</div>
<br><br><br>
#endforeach
#endif
Just edit your foreach loop, you have to pass an array as options to rout using route param name as array key:
#foreach($jobPosts->where('user_id', $employerProfile->user_id) as $jobPost)
<h5>{{ $jobPost['job_title'] }}</h5>
#endforeach

Laravel Collection get one of values by key

I'm new to Laravel and I'm trying to get one of the values in one collection by one ID retrieved from another collection.
My function returns 2 Collections:
public function index()
{
$category = BlogCategory::all(['id', 'name']);
$post = BlogPost::orderBy('id', 'desc')->take(14)->get();
return view('blog.index', ['posts' => $post], ['categories' => $category]);
}
In a foreach loop I'm getting values from collections:
#foreach($posts as $post)
#if($loop->iteration > 2)
<div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
<a href="#">
<img src="#" alt="">
<p class="post-category">{{ $categories->get($post->category_id) }}</p>
<h5 class="post-title">{{ $post->title }}</h5>
</a>
</div>
#endif
#endforeach
I'm partially getting the result as you can see in the image below, but I want to get only the name.
Here is the code that I'm trying to figure out
{{ $categories->get($post->category_id) }}
If there is a better or correct way to do it, let me know.
Blog Posts migration:
public function up()
{
Schema::create('blog_posts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title');
$table->longText('content');
$table->mediumText('slug');
$table->bigInteger('author_id')->unsigned();
$table->bigInteger('category_id')->unsigned();
$table->timestamps();
$table->foreign('author_id')->references('id')->on('blog_authors');
$table->foreign('category_id')->references('id')->on('blog_categories');
});
}
You should put in place the relationships between BlogPost and BlogCategory models, seen that you already have a category_id field in BlogPost model, i.e.:
in BlogPost Model:
public function category(){
return $this->belongsTo(\App\BlogCategory::class);
}
in BlogCategory Model:
public function posts(){
return $this->hasMany(\App\BlogPost::class);
}
Next you can eager load categories with the $posts in your controller with only two queries:
public function index()
{
$posts = BlogPost::with('category')->orderBy('id', 'desc')->take(14)->get();
return view('blog.index', compact('posts'));
}
Then in your view you can access each $post->category object directly because eager loaded in the controller:
#foreach($posts as $post)
#if($loop->iteration > 2)
<div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
<a href="#">
<img src="#" alt="">
<p class="post-category">{{ $post->category->name }}</p>
<h5 class="post-title">{{ $post->title }}</h5>
</a>
</div>
#endif
#endforeach
It could be optimized, first, you need to make relation one to many from categories to posts
first: make sure that you have in posts migrations category_id column
Second: Open Category Model and write this method this will allow you to fetch posts that belong to the category
public function posts(){
return $this->hasMany(\App\Post::class);
}
Third: open shop model and write this method this will allow you to fetch category that belongs to the post
public function catgeory(){
return $this->belongsTo(\App\Category::class);
}
Finally: you will edit your view like this one
#foreach($posts as $post)
<div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
<a href="#">
<img src="#" alt="">
<p class="post-category">{{ $post->category->title }}</p>
<h5 class="post-title">{{ $post->title }}</h5>
</a>
</div>
#endforeach
and of course, you wouldn't call categories in your controller anymore
public function index()
{
$post = BlogPost::orderBy('id', 'desc')->take(14)
->with('category')->get();
return view('blog.index', ['posts' => $post]);
}
Maybe it better use a relation to drive this situation. You can load in the controller the data in this way.
In the Model Post:
function categories(){
return $this->belongsToMany('App\BlogCategory')->select(array('id', 'name');
}
Maybe is hasOne -> the relationship if you don't have a table pivot...
In the Controller:
public function index()
{
$data['posts'] = BlogPost::orderBy('id', 'desc')->take(14)->with('categories')->get();
return view('blog.index', $data);
}
In the View:
#foreach($posts as $post)
#if($loop->iteration > 2)
<div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
<a href="#">
<img src="#" alt="">
<p class="post-category">{{ $post->categories->name }}</p>
<h5 class="post-title">{{ $post->title }}</h5>
</a>
</div>
#endif
#endforeach
this line $categories->get($post->category_id) return for you an array of category, so the solution for you here is just like bellow:
{{ $categories->get($post->category_id)['name'] }}

Fetch first image from foreign key table Laravel

Reference: Fetch first image from foreign key table but this time in Laravel.
I started playing with Laravel and I want to take first image from every post and show these in my blade.
$secondpost = DB::table('posts')
->orderBy('id', 'desc')
->skip(1)
->take(8)
->get();
foreach ($secondpost as $spost)
$secondph = DB::table('post_images')
->select('filename')
->where('post_id', $spost->id)
->limit(1)
->get()
->pluck('filename');
return view ('pages.index', compact('firstp', 'fph', 'secondpost', 'secondph'));
<div class="row">
#foreach ($secondpost as $secondp)
<div class="col-lg-3 col-md-3 col-sm-6 col-xs-6 post-ab">
<div class="row">
#foreach ($secondph as $sph);
<img src="{{url($sph)}}" class="imgpost" alt="">
#endforeach
<div class="bottomleft">
<p class="ab-desc">{{$secondp->marca}} {{$secondp->model}}</p>
<p class="ab-desc">{{$secondp->pret}} Eur</p>
</div>
</div>
</div>
#endforeach
</div>
This code load only one image for every img src. Post_id is foreign key for posts table id.
There are few things you need to confirm.
You have created models for the table like Post for posts table and PostImages for post_images table. If not, follow the documentation. https://laravel.com/docs/5.8/eloquent
You have created the hasMany relationship in your post model with post_images. Like:
In Post model.
/**
* Get the images for the post.
*/
public function images()
{
return $this->hasMany('App\PostImage');
}
Then change in your controller to use early loading, Like:
$secondpost = \App\Post::with("images")
->orderBy('id', 'desc')
->skip(1)
->take(8)
->get();
And now the view looks like:
<div class="row">
#foreach ($secondpost as $secondp)
<div class="col-lg-3 col-md-3 col-sm-6 col-xs-6 post-ab">
<div class="row">
#php
$image = $secondp->images->first();
#endphp
<img src="{{url($image->filename)}}" class="imgpost" alt="">
<div class="bottomleft">
<p class="ab-desc">{{$secondp->marca}} {{$secondp->model}}</p>
<p class="ab-desc">{{$secondp->pret}} Eur</p>
</div>
</div>
</div>
#endforeach
</div>
Solution: 2
You can create another relationship with hasOne to get a single image like:
// In your Post model.
/**
* Get the default image for post.
*/
public function default_image()
{
return $this->hasOne('App\PostImage')->orderBy("id");
}
Make change in controller to use ->with("default_image").
And in view you can just use like:
$secondp->default_image->filename

Passing data through pivot tables?

I have three tables, the activity, the category and the activity_categories table.Each activity may belong to many categories therefore the category_id and activity_id are saved in activity_categories.
I am trying to get only one category per product, because to display use one category image per activity but on search I have to show them in all belonging categories.I have created my models as follow:
class Activity extends Model
{
protected $table = "activities";
public function category()
{
return $this->belongsToMany('App\Category','activity_categories');
}
}
//Controller
public function userActivities()
{
$user_id = Auth::user()->id;
$activities = Activity::all()->where('user_id', $user_id);
return view('user_profile.activities', compact( 'activities' ));
}
//View
#foreach($activities as $activity)
<div class="col-lg-4 col-md-4 col-xs-12" id="profile-card">
<div class="widget-head-color-box navy-bg p-lg text-center"
style="background-image: url('{{asset('/images/categories/'.$activity->category->first()->image)}}')">
<img src="/storage/profile/{{Auth::user()->image}}" class="img-small-profile" alt="profile">
<button id="heart-favorite" class="btn btn-danger btn-circle btn-outline"
type="button"><i
class="fa fa-heart"></i></button>
</div>
<div class="widget-text-box">
<h3 class="media-heading m-t-md"><b>{{$activity->title}}</b></h3>
<h5 class="media-heading m-t-md" style="text-align: justify">
{{$activity->description}}<br><br>
</h5>
</div>
</div>
#endforeach
When i use dd($activity->category->first()->image) it shows the data but when i place the same in the view id shows the error "Trying to get property of non-object"

Laravel view links and web.php routes messed up

I'm making a forum with themes and topics. If a user clicks on a theme, he/she gets to see all the topics within that theme. Here we encounter the first problem. In the theme.blade.php I have a title: <span class="card-title">{{ $theme->theme_title }} - Topics</span>. This title is supposed to show the title of the theme that the user clicked on. But it shows (just a wild guess) some random theme title from the database that is not even connected to this topic.
Now I made an extra view for the user. If the user clicks on a topic from the selected theme. He/she is supposed to redirect to the topic that he/she clicked on but instead its shows (again) some random topic from the database that is not connected to the topic/theme at all. Instead of the topic that the user clicked on. In this GIF http://imgur.com/a/vOQFT you can see the problem If u look at the profile picture and username. Maybe the problem is in the Web.phpor somewhere else, I don't know. Sorry for the long story but I couldn't figure out how say this in a better way. I think I switched some things up in the code.
Here is the every file of code where this problem may occur
Web.php
Route::get('/', 'ThemesController#index')->name('home');
Route::get('/theme/{theme_id}/topics', 'ThemesController#show')->name('showtheme');
Route::get('/theme/{theme_id}/topics/{topic_id}', 'TopicsController#show')->name('showtopic');
Route::group(['middleware' => 'App\Http\Middleware\AdminMiddleware'], function() {
//THEMES
Route::get('/theme/{theme_id}/edit', 'ThemesController#edit')->name('edittheme');
Route::patch('/theme/{theme_id}/edit', 'ThemesController#update')->name('updatetheme');
Route::get('/theme/create', 'ThemesController#create')->name('createtheme');
Route::post('/theme/create', 'ThemesController#save')->name('savetheme');
Route::delete('/theme/{theme_id}/delete', 'ThemesController#destroy')->name('deletetheme');
//TOPICS
Route::get('/theme/{theme_id}/topics/{topic_id}/edit', 'TopicsController#edit')->name('edittopic');
Route::patch('/theme/{theme_id}/topics/{topic_id}/edit', 'TopicsController#update')->name('updatetopic');
Route::get('/theme/{theme_id}/topics/create', 'TopicsController#create')->name('createtopic');
Route::post('/theme/{theme_id}/topics/create', 'TopicsController#save')->name('savetopic');
Route::delete('/theme/{theme_id}/topics/{topic_id}/delete', 'TopicsController#destroy')->name('deletetopic');
});
Route::get('user/profile', 'UserController#profile')->name('showprofile');
Route::post('user/profile', 'UserController#update_avatar');
Theme.blade.php (The list of every topic within the theme)
<div class="col s12">
<div class="card">
<div class="card-content"><span class="card-title">{{ $theme->theme_title }} - Topics</span>
<div class="collection">
#foreach($topics as $topic)
<a href="{{ route('showtopic', ['theme_id' => $theme->id, 'topic_id' => $topic->id ]) }}" class="collection-item avatar collection-link"><img src="/uploads/avatars/{{ $topic->user->avatar }}" alt="" class="circle">
<div class="row">
<div class="col s6">
<div class="row last-row">
<div class="col s12"><span class="card-title">{{ $topic->topic_title }}</span>
<p>{!! str_limit($topic->topic_text, $limit = 125, $end = '...') !!}</p>
</div>
</div>
<div class="row last-row">
<div class="col s12 post-timestamp">Posted by: {{ $topic->user->username }} op: {{ $topic->created_at }}</div>
</div>
</div>
<div class="col s2">
<h6 class="title center-align">Replies</h6>
<p class="center replies">{{ $topic->replies->count() }}</p>
</div>
<div class="col s2">
<h6 class="title center-align">Status</h6>
<div class="status-wrapper center-align"><span class="status-badge status-open">open</span></div>
</div>
<div class="col s2">
<h6 class="title center-align">Last reply</h6>
<p class="center-align"></p>
<p class="center-align">Tijd</p>
</div>
</div>
</a>
#endforeach
</div>
</div>
</div>
</div>
ThemesController.php (Only show method)
public function show($id)
{
$theme = Topic::find($id)->theme;
$topics = Theme::find($id)->topics;
return view('themes.theme')->with('topics', $topics)->with('theme', $theme);
}
TopicsController.php(Only show method)
public function show($id)
{
$theme = Theme::find($id);
$topic = Topic::find($id);
return view('topics.topic')->with('theme', $theme)->with('topic', $topic);
}
Thanks for looking at my code. This problem has been sitting here for quite a while and I want to move on. Thanks for your help!
Your controller code simply finds the theme with ID $id, and the topic (singular!) with ID $id. That particular topic may not appear in that particular theme at all. They likely have nothing to do with each other.
To find the topics belonging to the theme with ID $id, you would do this:
$theme = Theme::find($id)->with('topics');
(this assumes your model relationships are set up correctly, you have not show us those). See the docs on eager loading.
To access the topics in your view, do something like this:
#foreach ($theme->topics as $topic)
...
{{ $topic->user->username }}
...
While developing, you can simply
return $theme;
in your controller to see the structure of the data, so you can work out how to handle and iterate over it.

Categories