Display user name from another table Laravel 8 - php

Hellow guys,
so I have 2 tables
is Listings
is Users
in Listings I have some columns, one is user_id, and is related to users tables.
I want to display the user name related to the user table.
in the index blade, I use some tags.
But when I use ->rightjoin("users", "users.id", "=", "listings.user_id") it's works but,
the join broke my tags make them default, same with others posts.
public function index(Request $request)
{
$listings = Listing::where('is_active', true)->with('tags')
//->rightjoin("users", "users.id", "=", "listings.user_id") //don't show tags of the posts
->orderBy('listings.created_at', 'desc')
->get();
//check if posts ar listing by last date or something
$tags = Tag::orderBy('name') // variable displayed in view
->get();

You could just use the with method to get the related user like this
public function index(Request $request) {
$listings = Listing::where('is_active', true)->with(['user', 'tags'])
->orderBy('listings.created_at', 'desc')
->get();
}
but make sure that you add to your Listing model the correct relation like this
Listing Model
public function user() {
return $this->belongsTo(User::class);
}

I recommend this code for controller:
public function index(Request $request) {
return $listings = Listing::query()
->where('is_active', true)->with(['user', 'tags'])
->orderBy('listings.created_at', 'desc')
->get();
}
In the models section, I suggest you put this code: ‌
public function user() {
return $this->belongsTo(User::class);
}
I suggest you fill in the fields foreignKey, ownerkey in relation: as in the following example:
public function user()
{
return $this->belongsTo(User::class, 'user_id', 'id');
}

Related

Laravel Eloquent Model with relationship

I have implemented eloquent relationship in my code but Laravel unable to read the function that I created to map the eloquent relationship in the model.
User Model
public function products(){
return $this->hasMany(Product::class,'userid');
}
Product Model
public function users(){
return $this->belongsTo(User::class);
}
Product Controller
$products = Product::with('Users')->Users()->where('users.isActive',1)->get();
return view('product',compact('products'));
I keep getting error from the product controller, I also attached the error that I current encountered as below.
How can I get all the product and user data with the where condition such as "Users.isActive = 1".
Thanks.
You can use whereHas to filter from a relationship.
$products = Product::with('users')
->whereHas('users', function ($query) {
$query->where('isActive', 1);
})
->get();
Also it is generally a good idea to use singular noun for belongsTo relationship because it returns an object, not a collection.
public function user() {
return $this->belongsTo(User::class);
}
$products = Product::with('user')
->whereHas('user', function ($query) {
$query->where('isActive', 1);
})
->get();
EDIT
If you want to retrieve users with products you should query with User model.
$users = User::with('products')
->where('isActive', 1)
->get();
Then you can retrieve both users and products by
foreach($users as $user) {
$user->products;
// or
foreach($users->products as $product) {
$product;
}
}
You can use whereHas() method for this purpose. Here is the doc
$products = Product::with('users')->whereHas('users', function (Illuminate\Database\Eloquent\Builder $query) {
$query->where('isActive', 1);
})->get();
$users = $products->pluck('users');
return view('product',compact('products'));
You have a typo after the with, is users instead of Users and you're redundant about the Query Builder, remove the ->Users():
Before:
$products = Product::with('Users')->Users()->where('users.isActive',1)->get();
return view('product',compact('products'));
After:
$products = Product::with('users')->where('users.isActive',1)->get();
return view('product',compact('products'));
Fix that and all should work.

How to filter entries via hasMany relationship in Laravel

I'm trying write an website with Laravel (current version is 5.7) and I have 3 models as: Post, User and Fav. I'm using a simple form to add posts to "favs" table which has 3 columns as; id, user_id and post_id. And I want to list posts that user added favorites bu I can't use "hasMany" method properly.
I can use variables like; $post->user->name but I can't figure it out how to use relationship with "favs" table.
Post Model
public function user() {
return $this->belongsTo('App\User');
}
public function favs() {
return $this->hasMany('App\Fav');
}
Fav Model
public function users() {
return $this->hasMany('App\User');
}
public function posts() {
return $this->hasMany('App\Post', 'post_id', 'id');
}
User Model
public function posts() {
return $this->hasMany('App\Post');
}
public function favs() {
return $this->hasMany('App\Fav');
}
Controller
public function user($id){
$favs = Fav::orderBy('post_id', 'desc')->get();
$user = User::find($id);
$posts = Post::orderBy('id', 'desc')->where('user_id', $id)->where('status', '4')->paginate(10);
return view('front.user')->with('user', $user)->with('posts', $posts)->with('favs', $favs);
}
The Fav model only has one User and Post each, so you need to use belongsTo() instead of hasMany and change the method names to singular. You can also remove the additional parameters in post() since they're the default values.
public function user() {
return $this->belongsTo('App\User');
}
public function post() {
return $this->belongsTo('App\Post');
}
Loading all Posts that a user has favorited:
$user->favs()->with('post')->get();
The with() method is used to eager load the relationship.
Now you can loop through the Favs:
#foreach($favs as $fav)
{{ $fav->post->name }}
#endforeach
I think you can change these two lines of your code to
$posts = Post::orderBy('id', 'desc')->where('user_id', $id)->where('status', '4')->paginate(10);
return view('front.user')->with('user', $user)->with('posts', $posts)->with('favs', $favs);
to
$posts = Post::where('user_id', $id)->where('status', '4')->latest()->paginate(10);
return view('front.user', compact('user', 'posts', 'favs'));
And for retrieving favorite posts of an user,
if you will change the fav table to make it a pivot table only to handle a many to many relationships between Post and User, you can get it as $user->posts, for a separate model, I think you can consider something like $user->favs and in view
In Fav model
public function user() {
return $this->belongsTo('App\User');
}
public function post() {
return $this->belongsTo('App\Post');
}
and in view
#foreach ( $user->favs as $fav )
{{ $fav->post->id }}
#endforeach
If an User, per example, have many Favs you need to use a Iteration Block, like foreach.
Example:
foreach($user->favs as $fav) {
dd($fav) // do something
}
Ps.: Be careful not to confuse hasMany and belongsToMany.

How to create a relationship between User and Posts in Laravel

I have a blog and want to include the Users Name when shown to the public.
When creating the blog I make sure to include the user_id in the blogs table
In my Blog model I have the following:
public function users()
{
return $this->belongsTo(User::class);
}
In my Users model I have:
public function blogs()
{
return $this->hasMany(Blog::class);
}
In my Blog Controller I have:
public function index(User $user)
{
$users = User::get();
$blogs= DB::table('blogs')->where('user_id', '=', $users->id)->orderBy('id', 'DESC')->paginate(6);
return view('blogs.index',compact('blogs'));
}
Then in my view:
#foreach($blogs as $blog)
<h1>{{$blog->title}}</h1>
Source:{{$blog->users->first_name}} // This does not work
Source:{{$blog->first_name}} // This does not work either
#endforeach
I thought I could do something like this to show the names:
{{ $blogs->users->first_name }} {{ $blogs->users->last_name }}
But this isn't working either...
Try this:
#foreach($blogs as $blog)
<h1>{{$blog->title}}</h1>
{{$blog->user->first_name}}
#endforeach
And on your Blog Model
public function user()
{
return $this->belongsTo(User::class);
}
In your Blog controller the variable $blog needs to be $blogs. You also have extra characters (right parenthesis) in your Blade. It should be:
#foreach($blogs as $blog)
Source: {{ $blog->user->first_name }}
...
#endforeach
Blog Model
This function replaces the old "users" function, as only one user is returned (belongsTo is a singular relationship).
class Blog extends Model
{
public function user()
{
return $this->belongsTo('App\User');
}
}
User Model
public function blogs()
{
return $this->hasMany('App\Blog');
}
Controller Function
And, as such, you can cut down your controller code, including removing the redundant elements.
public function index(User $user)
{
$blogs = Blog::where('user_id', '=', $user->id)->orderBy('created_at','desc')->paginate(6);
return view('blogs.index', compact('blogs'));
}
The way you did is called Query Builder
$blogs= DB::table('blogs')->where('user_id', '=', $users->id)->orderBy('id', 'DESC')->paginate(6);
Query Builder does not support lazy loading, cause lazy loading is only supported for the Eloquent method
$blog->users->first_name
For Eloquent way you can try this instead:
$blogs = Blog::where('user_id', $user->id)->get()
foreach($blogs as $blog){
dd($blog->user); // you will get the user detail here
}
For lazy loading have a performance issue when come to load heavy data so to prevent lazy loading can use this
$blogs = Blog::with('user')->where('user_id', $user->id)->get()
For more information can look at Eloquent Relationship Documentation
For query builder, the only way to link your user is use join, which will be something like this
$blogs = DB::table('blogs')
->join('users', 'users.id', '=', 'blogs.user_id')
->get();
foreach($blogs as $blog){
dd($blog->first_name) // user first name
}
For more information can look at Query Builder Join
BlogController.php
public function index(){
$blogs = Blog::with('user')->get();
return view('blogs.index')->with('blogs',$blogs);
}
Blog.php
public function user()
{
return $this->belongsTo('App\User');
}
User.php
public function blogs()
{
return $this->hasMany('App\Blog');
}

Query with two laravel models and return result

I have two models, User and Post
User Model:
public function posts()
{
return $this->hasMany('App\Post');
}
Post Model:
public function user()
{
return $this->belongsTo('App\User');
}
In my controller I have a public function which has:
$users = User::orderBy('is_ban', 'desc')->paginate(10);
$posts = Post::orderBy('created_at', 'desc')->paginate(10);
Which is working as expected.
I also have one column in users table `is_ban' It's of boolean type.
I am looking for a query which will return the following:
Only get post which has been made by the user which has is_ban=false
perhaps i haven't understood you, but i hope it will help. You can add it to your Post model
public function getBannedUsersPosts()
{
return self::whereIn('user_id', User::where('is_ban', 0)->pluck('id'))->get();
}

Laravel 5.2 Search all records but return only parent elements' data

I made a search function that searches name and content fields of all posts in the database. Some of these posts are in relation (parents and children). I have a problem as if my search returns a hit in a child post, I would like to return only parent data (to minimise the load).
My Post model:
public function children()
{
return $this->hasMany('App\Post','parent_post_id','id');
}
public function children_count()
{
return $this->children()
->selectRaw('parent_post_id, count(*) as answers')
->groupBy('parent_post_id');
}
public function parents()
{
return $this->hasOne('App\Post','id','paren_post_id');
}
public function author()
{
return $this->hasOne('App\User', 'id', 'user_id');
}
My search query:
$posts = Post::with('children')
->with('children_count')
->with('author')
->where('name','like','%'.$search_term.'%')
->orWhere('content','like','%'.$search_term.'%')
->orderBy('created_at','desc')
->groupBy('id')
->paginate(10);
Example: Post#1 has two children, Post#2 and Post#3. My search finds data in Post#3, now I would like it to return data of Post#1.
EDIT:
I see that I need to explain more what exactly would I like to achieve.
Posts table structure:
id
name
slug
content
user_id
parent_post_id
updated_at
created_at
I am searching name and content fields of each post (author (user_id) is irrelevant at this point). When search finds a hit in child post (has parent_post_id set to parent's id), I only want to get parent's data (id, slug, name, content etc.)
I was able to achieve this with:
$posts = DB::table('posts as a')
->leftJoin('posts as b', 'b.parent_post_id', '=', 'a.id')
->where('a.name','like','%'.$search_term.'%')
->orWhere('a.content','like','%'.$search_term.'%')
->orWhere('b.name','like','%'.$search_term.'%')
->orWhere('b.content','like','%'.$search_term.'%')
->select('a.*')->orderBy('a.created_at','desc')->paginate(10)
But was then unable to successfully count all children that returned parent has. This might also give some ideas how to wrap this Laravel way
Can anyone point me in the right direction?
class Post extends Model{
public function children()
{
return $this->hasMany(Post::class, 'parent_post_id', 'id');
}
public function children_count()
{
return $this->children()
->selectRaw('parent_post_id, count(*) as answers')
->groupBy('parent_post_id');
}
public function parents()
{
return $this->hasOne(Post::class, 'id', 'parent_post_id');
}
public function author()
{
return $this->hasOne(User::class, 'id', 'user_id');
}
}
$posts = Post::with(['children_count', 'author', 'children'])
->whereHas('author', function ($query) use ($search_term) {
$query->where('name', 'like', '%' . $search_term . '%');
})
->orWhere('content','like','%' . $search_term . '%')
->orderBy('created_at', 'desc')
->paginate(10);

Categories