Get the user name and comment with article id in Laravel - laravel

I have 3 tables users, comments, and articles. I have a route like this:
Route::get('/article/{id}', 'ArticlesController#view');
What I want is when I accessing that route I will get User Name and their comment in this article id.
so here's my view function in ArticlesController:
public function view($id){
$article = Article::with('comments')->find($id);
return view('front.single',compact('article'));
}
and here's my single.blade.php code:
<div class="single-grid">
#section('content')
<h1>{{ $article->title }}</h1>
<p>{{ $article->content }}</p>
#show
</div>
<div class="comment-list">
#foreach($article->comments as $comment)
<ul class="comment-list">
<div class="comment-grid">
<img src="/images/avatar.png" alt=""/>
<div class="comment-info">
<h4>{{ $comment->user->name }}</h4>
<p>{{ $comment->comment }}</p>
<h5>{{ $comment->created_at->diffForHumans() }}</h5>
Reply
</div>
<div class="clearfix"></div>
</div>
</ul>
#endforeach
</div>
I'm not sure what how to do it since it gives me error like this:
"Call to undefined relationship [comment] on model [App\User]."
I already define the relation in each model. here's my articles model:
public function comments(){
return $this->hasMany(Comment::class);
}
public function user(){
return $this->belongsTo(User::class);
}
My comment model:
public function article(){
$this->belongsTo(Article::class);
}
public function user(){
$this->belongsTo(User::class);
}
and here's my User model:
public function articles(){
return $this->hasMany(Article::class);
}
public function comments()
{
return $this->hasMany(Comment::class);
}
public function publish(Article $article){
$this->articles()->save($article);
}
here's my table structure:
-users(id,name,email,password,remember_token,created_at,updated_at)
-comments(id,user_id,article_id,comment,created_at,updated_at)
-articles(id,user_id,title,content,created_at,updated_at)
so how can I can User Name just by using this route? thanks.

on Your Comment Model, You need to replace articles to article
public function article(){
$this->belongsTo(Article::class);
}
also, if you want to get user specific comments, than you need to change your controller action code from
$article = Article::with('user.comment')->find($id) to
$article = Article::with('user.comments')->find($id);

I think that your issue comes from the use of compact function : an array is passed to the view instead of an object.
Can you try it like this :
// Controller
public function view($id) {
$article = Article::findOrFail($id);
return view('front.single', $article);
}
<!-- View -->
#foreach($article->comments as $comment)
{{ $comment->user->name }}
{{ $comment->comment }}
{{ $comment->created_at->diffForHumans() }}
#endforeach

Related

I want to displaying comments for each post

hello I just moved from php native and want to try relationships in laravel, so I want to display a post and each comment and the name of user who comments so that when looped the post has a comment that has a relationship with it.
So this is my HomeController.php :
public function index() {
$posts = Post::all();
$comment = Comment::all();
return view('home', [
'posts' => $posts,
'comments' => $comment
]);
}
My Post.php :
public function comments() {
return $this->hasMany(Comment::class);
}
public function user() {
return $this->belongsTo(User::class);
}
My Comments.php :
public function post() {
return $this->belongsTo(Post::class);
}
public function user() {
return $this->belongsTo(User::class);
}
My User.php :
public function post() {
return $this->hasMany(Post::class);
}
My home.blade.php :
#foreach ($posts as $post)
<div class="box-post">
<p>{{ $post->user->name }}</p>
<p>{{ $post->post_content}}</p>
<button>Comment</button>
</div>
#foreach ($comments as $comment)
<div class="box-post">{{ $comment->comment_content }} </div>
#endforeach
#endforeach
the code above runs with the post displayed along with the author but all the comments also appear in all posts, I have searched for references and tried to change the comments value in Controller but the results are still the same so I made the comments appear in each post *$comment = Comment::all();.
what I want is to display posts and comments that relate to each post, like a twitter feature that can reply to people's tweets.
Thx you..
Your relations builded well, so just can simply use $post->comments can get all comments related on each post.
#foreach ($posts as $post)
<div class="box-post">
<p>{{ $post->user->name }}</p>
<p>{{ $post->post_content}}</p>
<button>Comment</button>
</div>
#foreach ($post->comments as $comment) // make changes here
<div class="box-post">{{ $comment->comment_content }} </div>
#endforeach
#endforeach
public function index() {
$posts = Post::with('comments')->get();
return view('home', [
'posts' => $posts,
]);
}
then in blade
#foreach ($posts as $post)
<div class="box-post">
<p>{{ $post->user->name }}</p>
<p>{{ $post->post_content}}</p>
<button>Comment</button>
</div>
#foreach ($post->comments as $comment)
<div class="box-post">{{ $comment->comment_content }} </div>
#endforeach
#endforeach
You have done fine job building models and their relationship.
I recommend you change how you call post query.
public function index(Request $request) {
// add eager loading comments for each post and user
$posts = Post::with('comments', 'user')->get();
// eager loading user is needed, cause in blade you call $post->user->name
// calling comments will no longer needed
// return only $posts
return view('home', compact('posts'));
}
And inside your blade, you can call comments from each post, like this.
#foreach ($posts as $post)
<div class="box-post">
<p>{{ $post->user->name }}</p>
<p>{{ $post->post_content}}</p>
<button>Comment</button>
</div>
#foreach ($post->comments as $comment)
<div class="box-post">{{ $comment->comment_content }} </div>
#endforeach
#endforeach
That's it and if you use barryvdh/laravel-debugbar , you will see there are only 3 queries run, each one from table posts, comments and users.
And for comments query and users query, not all rows will be fetched,
only related to fetched posts from the 1st query.
Have fun using Laravel Framework!
Your PHP native knowledge/expertise will be very useful and speed up your learning/mastering process.

Show category posts in Laravel is not working

I want to show posts that are in a category by clicking on them, but when I click on a category,$articles in category.blade.php returns null.
$articles should return articles that have a specific category
this is my index.blade.php:
<div class="tab-pane fade" id="show-categories" role="tabpanel">
<h6 class="sidebar-title">Categories</h6>
<div class="row link-color-default fs-14 lh-24">
#foreach($categories as $category)
<div class="col-6">
<a href="{{ route('cms.category', $category->id) }}">
{{ $category->name }}
</a>
</div>
#endforeach
</div>
</div>
category.blade.php:
#extends('layouts.app')
#section('content')
#forelse ($articles as $article)
<h1>{{$article->title}}</h1>
#empty
<span>array is empty</span>
#endforelse
#endsection
router:
Route::get('cms/categories/{category}', [articlesController::class, 'category'])->name('cms.category');
and articlesController:
public function category(Category $category)
{
return view('cms.category')
->with('category', $category)
->with('articles', $category->articles()->searched()->simplePaginate(3))
->with('categories', Category::all())
->with('tags', Tag::all());
}
Please, don't forget to define the relationship from Category to Article on your model. Like: one category has many articles. For example:
On your Category.php model:
public function articles()
{
return $this->hasMany(Article::class);
}
Then on your, controller, you may call the relationship like this way:
public function category(Category $category)
{
$articles = Category::with("articles")->where("id", $category->id)->simplePaginate(3);
return view('cms.category')
->with('category', $category)
->with('articles', $articles)
->with('categories', Category::all())
->with('tags', Tag::all());
}
Please share the model file and second I prefer to write the category method in a different way.
public function category($category_id)
{
try {
$articles= Article::where('id', $category_id)->get();
return view('cms.category', $articles);
} catch (\Throwable $th) {
Log::error($th->getMessage());
}
}
Let me know if you still face any issue. Try to use dd $articles ..

How to Call/Display Foreach Loop after Login

I had problem on calling page inside Foreach Loop.Although It is Okay before I click Login, but when I'd try to login,only the html tag where loaded and foreach loop cannot... On my HomeController extends Controller
public function index()
{
return view('pages.welcome');
}
on where I call welcome page. and inside of it which is foreach loop.
<div class="row">
<div class="col-md-8">
#foreach ($posts as $post)
<div class="post">
<h3>{{ $post->title }}</h3>
<p>{{ substr($post->body, 0,300) }}
{{ strlen($post->body) > 300 ? "..." : " " }}</p>
Read More...
</div>
<hr>
#endforeach
</div>
</div>
And I think the problem is my route:
Route::get('/home', 'HomeController#index');
You haven't passed the $posts variable to the view.
Change
public function index()
{
return view('pages.welcome');
}
To something like this:
public function index()
{
$posts = \App\Post::all(); //Assuming your model is called "Post" in the App namespace
return view('pages.welcome', compact('posts'));
}
NOTE: compact('posts') is just a shortcut for ['posts'=>$posts]

get category name in a post record

I have a list containing article posts from all categories. I want to display the category tag in each post on the list and I tried this :
<article class="post bg z-depth-1">
<?php foreach ($article_list as $article): ?>
<div class="post-img">
<a href="post.html">
<img class="retina" src="{{ asset('image/' . $article->image) }}" width="820" height="500" alt="Post Image">
</a>
</div>
<div class="post-content">
<div class="post-header center-align">
<div class="tags">
{{ $article->category->title }}</div>
<h2 class="post-title">{{ $article->title }}</h2>
<div class="date">Posted on {{ Carbon\Carbon::parse($article->created_at)->format('F j, Y') }}</div>
</div>
<div class="post-entry">
<p>sss</p>
</div>
<div class="post-footer">
<div class="post-footer-item">
<span class="text">Read More</span> <i class="fa fa-arrow-circle-right"></i>
</div>
</div>
</div><!-- .post-content -->
<?php endforeach ?>
</article><!-- .post -->
and it gave me error Undefined property: stdClass::$category and I don't know why, I already define the relationship in each model Article and Category. Thanks for the help!
In Article model :
public function category()
{
return $this->belongsTo('App\Category', 'category_id');
}
In Category model :
public function article() {
return $this->hasMany('App\Article', 'category_id');
}
Controller :
public function index() {
$article_list = Article::all();
return view('article/index', compact('article_list', $article_list));
}
What you need to do is eager load those relationships in your controller.
When you pull the records do it like this:
$article_list = Article::with('category')->get();
https://laravel.com/docs/5.3/eloquent-relationships#eager-loading
Change this: $article->category->title
To this: $article->category()->title
When you define the relationship in your model you are also creating a function not a property called category.
public function category()
{
return $this->belongsTo('App\Category');
}
In Category model :
public function article() {
return $this->hasMany('App\Article');
}
Controller :
public function index() {
$article_list = Article::all();
return view('article/index', compact('article_list'));
}
This should work for you now like this.

Is there a more efficient way for grabbing the count of a model within the view? Laravel

I have Images. Each image has comments, and each comment has likes. In my view I'm wanting to display the number of likes a comment has by doing something like this:
#foreach ($images as image)
<img href="$image->url">
<div class="comment-box">
#foreach ($image->comments as $comment)
<div class="comment">
<span class="comment-owner">{{ $comment->owner()->name }}</span> {{ $comment->body }}
<div class="likes">
{{ $comment->likes()->count() }} // ** HERE IS MY N+1 PROBLEM **
</div>
</div>
#endforeach
</div>
#endforeach
However now I'm fetching a query each time there is a comment. There could be hundreds of comments on a page, so id be getting hundreds of queries just to find the count() for likes.
I believe there is a way you can grab the count in a controller by doing something like
DB::raw('count(*) as like_count')
but I do not know how to implement this in my situation. Can I put this kind of thing in my model so that I can always call something like {{ $comment->likes()->like_count }}? How can I make $comment->likes->count() work without having the N+1 problem?
Here is some more code:
Media Model
class Media extends Eloquent {
public function comments()
{
return $this->hasMany('Comment');
}
}
Comment Model
class Comment extends Eloquent {
public function media()
{
return $this->belongsTo('Media');
}
public function likes()
{
return $this->hasMany('Like');
}
}
Like Model
class Like extends Eloquent {
public function comment()
{
return $this->belongsTo('Comment');
}
}
My controller
public function imageViewer($id)
{
$images = Media::with(['comments' => function($query) {
$query->with('likes');
}])->where('resource_id', $id)->simplePaginate(1);
return View::make('image-viewer', compact('images'));
}
Why don't you just use blade's count like this count($comment->likes) assuming that $comment->likes gets the list of likes for a comment
#foreach ($images as image)
<img href="$image->url">
<div class="comment-box">
#foreach ($image->comments as $comment)
<div class="comment">
<span class="comment-owner">{{ $comment->owner()->name }}</span> {{ $comment->body }}
<div class="likes">
{{ count($comment->likes) }}
</div>
</div>
#endforeach
</div>
#endforeach
Thanks to #lukasgeiter for pointing out a mistake in the comments

Resources