Fetch first image from foreign key table Laravel - php

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

Related

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

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

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'] }}

Laravel 5.7 Comment count for different posts

I am stucked at point where i got comment count for posts but it shows count of all comments of all posts on every post. I would like to know how to output in blade comment count for post ID
here is controller:
$posts = $posts->orderBy("posted_at", "desc")
->paginate(config("blogetc.per_page", 10));
$comments = BlogEtcComment::all();
return view("blogetc::index", [
'posts' => $posts,
'title' => $title,
'comments' => $comments,
]);
blade:
#foreach($posts as $post)
<section class="blog_area p_120">
<div class="container">
<div class="row">
<div class="col-lg-8">
<div class="blog_left_sidebar">
<article class="blog_style1">
<div class="blog_img">
<img class="img-fluid" src="blog_images/{{$post->image_large}}" alt="">
</div>
<div class="blog_text">
<div class="blog_text_inner">
<div class="cat">
<a class="cat_btn" href="{{$post->url()}}">{{$post->slug}}</a>
<i class="fa fa-calendar" aria-hidden="true"></i>{{$post->created_at}}
<i class="fa fa-comments-o" aria-hidden="true"></i> {{count($comments)}}
</div>
<h4>{{$post->title}}</h4>
<p>{!! $post->generate_introduction(400) !!}</p>
<a class="blog_btn" href="{{$post->url()}}">Lasīt vairāk</a>
</div>
</div>
</article>
</div>
</div>
</div>
</div>
</section>
#endforeach
//Quickfix:
//assuming your posts table is called posts and that in your blogetccomments table //you have a post_id column pointing to the original post. Try something like
$posts = DB::table('posts')
->leftJoin('blogetccomments', 'posts.id', '=', 'blogetccomments.post_id')
->selectRaw('posts.*, count(blogetccomments.post_id) as commentcount')
->groupBy('posts.id')
->get();
In your blade template, Access the comments count for each post, as follows..
#foreach($posts as $post)
...
{{$post->title}}...
{{$post->commentcount}}
...
#endforeach
You can use withCount() to get count of comments for a specific post :
$posts = $posts->withCount('comments')
->orderBy("posted_at", "desc")
->paginate(config("blogetc.per_page", 10));
Above would require you to have comments relation on your Post Model :
Post Model :
public function comments()
{
return $this->hasMany(BlogEtcComment::class);
}
BlogEtcComment Model :
public function post()
{
return $this->belongsTo(Post::class);
}
And then in blade :
#foreach($posts as $post)
<p>Post : $post->id</p>
<p>Comments : $post->comments_count</p>
#endforeach

Laravel compact is not working

I'm trying to make a posting system, with a resource routing combination on the posts. When I try to run the app to view the posts, it returns an error stating that the posts could not be found within the view. I have the controller code for the index and the show functions:
public function index()
{
$posts = Post::latest()->get();
return view('view', compact('posts'));
}
public function show(Post $post)
{
return view('posts.show', compact('post'));
}
The view that I have for the app uses the post variable to display the posts:
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-2">
<div class="panel panel-default">
<!-- Posts will be displayed on the same panel -->
<div class="panel-body" id="view">
#foreach($posts as $post)
<article id="post">
<a href="/view/posts{{ $post->id }}">
{{ $post->title }}
</a>
<div class="body">
{{ $post->body }}
</div>
<!-- Footer for posts will include interaction features -->
</article>
#endforeach
</div>
</div>
</div>
</div>
</div>
Is there something that the laravel installation isn't doing correctly? Is the compact function set up correctly?
Your controller index function should be something like this:
public function index()
{
$posts = Post::get();
return view('posts.index', compact('posts'));
}
The return of the index action is wrong
return view('view', compact('posts'));
Change 'view' with 'posts'
Use compact('posts')
If you're a beginner checkout the laracasts video series to get a good understanding of the Laravel framework.

Laravel get profile name

I'm laravel newbie and I'm making simple CMS. So i have simple question:
I wan't when click on avatar - redirect to user profile (http://example.com/profiles/nickname/id)
In DB it saves that:
as you see author_id I have, now I need to get author name from users table:
And then generate url: http://example.com/profiles/Evaldas/2 (Evaldas, because author_id is 2 in topics table)
My routes file:
Route::get('topic/{tname}/{tid}', 'viewTopic#showTopic');
My viewTopic.php Controller:
<?php
namespace App\Http\Controllers;
use DB;
use View;
class viewTopic extends Controller
{
public function showTopic($tname, $tid)
{
return View::make('posts', [
'topics' => DB::table('topics')
->where('id', $tid)
->where('seo_title', $tname)
->first(),
'posts' => DB::table('posts')
->where('topic_id', $tid)
->select()
->get()
]);
}
}
And layout:
#extends('layouts.main')
#section('content')
<div class="media">
<div class="media-left">
<a href="HERE MUST BE HREF TO PROFILE">
<img class="media-object" src="http://localhost/uploads/avatars/2.jpg" style="width: 64px">
</a>
</div>
<div class="media-body" rel="#author{{ $topics->author_id }}">
<h4 class="media-heading">{{ $topics->title }}</h4>
#if(!empty($topics->text))
{{ $topics->text }}
#else
Message empty :(
#endif
</div>
#foreach($posts as $post)
<div class="media">
<div class="media-left">
<a href="HERE MUST BE HREF TO PROFILE">
<img class="media-object" src="http://localhost/uploads/avatars/1.png" style="width: 64px">
</a>
</div>
<div class="media-body" rel="#post{{ $post->pid }}">
{{ $post->text }}
</div>
</div>
#endforeach
</div>
#stop
Thanks so much in advance :)
If you want to use the Query Builder, you can use the join() method:
DB::table('posts')
->where('topic_id', $tid)
->join('users', 'user.id', '=', 'posts.author_id')
->select()
->get()
This way, the user information will be available:
$post->nickname
You can then build your URL using a laravel helper, for exemple, if you have a profile route:
<a href="{{route('profile', ['nickname' => $post->nickname, 'id' => $post->author_id]);}}">
An other method is to create models for your tables and define relationship between them.
See this: http://laravel.com/docs/5.1/eloquent-relationships
Using this method, you will be able to write things like $post->author->nickname

Categories