I have relations like this
User->hasMany->reviews
Review->belongsTo->user
Review->hasMany->ReviewAnswer
ReviewAnswer->belongsTo->Review
Now I try to display answers for specific review. My reviewAnswer table looks like:
Id, review ID, text
But the problem is when I do that:
#foreach($user->reviews as $data)
#foreach($data->reviewAnswers->where('review_id', $data->id) as $answer)
{{$answer->text}}
#endforeach
#endforeach
Then reviews displays okay, but I get the same answers for every review. How to repair that?
Make sure to check if all the relationships are correct. In this example, I assume that your models are stored in your app folder.
First, your User model should have reviews
public function reviews() {
return $this->hasMany("App\Review", "user_id", "id");
}
Next, set up your Review model to have answers
public function answers() {
return $this->hasMany("App\ReviewAnswer", "review_id", "id");
}
Then this is how you'll get all users with their respective reviews and answers
$users = User::with("reviews.answers")->get();
Finally, peform the loop in your view
#foreach($users as $user)
#foreach($user->reviews as $review)
#foreach($review->answers as $answer)
#endforeach
#endforeach
#endforeach
Try using the hasManyThrough() option which the eloquent models provide you.
Link: Laravel Eloquent Relations
This means in your case you would add:
class User extends Model {
public function reviewAnswers(
return $this->hasManyThrough(ReviewAnswer::class,Review::class);
)
}
and then simply access it in blade as:
#foreach($user->reviewAnswers() as $reviewAnswer) {
{{$reviewAnswer->text}}
}
Related
I have problem to get name from role_user table for each post. I have ACL, so i have 3 tables - users, roles, role_user.
My code looks like this:
Post model
public function user()
{
return $this->belongsTo(user::class);
}
User model.
public function posts()
{
return $this->hasMany(post::class);
}
Role model.
public function users()
{
return $this->hasmany(user::class);
}
PostController,
return view ('admin.posts',[
'posts' => Post::All()
]);
In blade I echo fx user name by:
#foreach ($posts as $post)
<tr>
<th scope="row">{{$post->id}}</th>
<td>{{$post->category->name}}</td>
**<td>{{$post->user->name}}</td>**
</tr>
#endforeach
But the problem is that i want to echo name of role ( from role_user table) for user who wrote post which i am looping.
update
Ok, i solved issue, but probaly there is a better wat. anyone?
I added to models:
User model:
public function roles()
{
return $this->belongsToMany(Role::class);
}
And changed role model:
public function users()
{
return $this->belongsToMany(user::class);
}
Post controller:
class PostController extends Controller
{
public function index()
{
return view ('admin.posts',[
'posts' => Post::with('user')->get(),
'roleUsers' => User::with('roles')->get()
]);
}
and in blade i am doing
#foreach ($posts as $post)
<tr>
<th scope="row">{{$post->id}}</th>
<td>
<p>
#foreach ($roleUsers as $roleUser)
#foreach($roleUser->roles as $role)
<p>
{{ $role->pivot->user_id === $post->user->id ? "Role: $role->name" : "" }}
</p>
#endforeach
#endforeach
I guess there could be a better solution.
Use withPivot() method on the relation. Instead of fetching it from the pivot attribute, it will be on the model, if fetched through the many to many relation.
public function users()
{
return $this->belongsToMany(user::class)->withPivot();
}
Then i would change the front end logic to something in the style of, assuming that all post would have a user with the given role, else you will need to do an if check.
#foreach ($roleUsers as $roleUser)
{{ $roleUser->roles->where('id', $post->user->id)->first()->name }}
#endforeach
You question has a lot of code, but this is the way i perceive it and hopefully it can get you closer to better understanding of it.
Ok i fix my problem, thank you for your help. I found many post's similar to my so I will show solution.
Realtion's:
User belongTo post.
Roles belongsToMany Users.
Users belongsToMany Roles.
DB structure:
users id|User_name
roles id|name
role_user id|user_id|role_id
And what I tried to achieve is while looping through all Post's in blade to display name of role which belongs to that post and solution is very simple.
#foreach ($posts as $post)
{{$post->user->roles->first()->name}}
#endforeach
I have two Table names are User and Role Table. I have set manyTomany relations between them using pivot table name Role_User in Laravel Eloquent.
Now, I want to show both table data in together a view using Eloquent Relationship.(e.g. I want to show in my view a user from users table contain which role in roles table )
Here, is my eloquent relations.
public function roles()
{
return $this->belongsToMany('App\Role');
}
public function users()
{
return $this->belongsToMany('App\User');
}
My, Eloquent Relationship Query.
$users=User::with('roles')->get();
return view('admin',compact('users'));
I'm try in my View.
#foreach($users as $user)
<tr>
<td>{{$user->name}}</td>
<td>{{$user->email}}</td>
<td>{{$user->roles->name}}</td>
<td></td>
</tr>
#endforeach
When you call $user->roles, you get a collection of the roles back. So if you want to display them all in a single string, all you have to do is implode the collection on that string:
<td>{{$user->roles->implode('name', ', ')}}</td>
Your $user->rules is instance of Collection of Role model. You can use one more foreach:
#foreach($users as $user)
//do something with user
#foreach($user->roles as $role)
{{$role->name}}
#endforeach
#endforeach
This will work in Laravel 5.0 and above
If we have two Model User and Mark. Then Inside the User Model make a function for relation with Mark. Example
public function marks()
{
return $this->hasMany('App\Models\Mark');
}
So, If you want to display the User name will all his marks. Then inside the controller perform following way.
public function getUserMarks(){
$result = User::select('email', 'name')->where('email', 'usermail#example.com')->with(['marks'])->get();
return view('welcome', compact('results'));
}
I have model named 'PropertyLead' as,
class PropertyLead extends Model
{
public function leadPropertyDetails()
{
return $this->belongsTo('App\Models\Property\Property', 'Property_id','id');
}
public function user()
{
return $this->belongsTo('App\Models\Access\User\User','user_id','id');
}
public function propertyRatings()
{
return $this
->hasMany('App\Models\Property\PropertyRating','Property_id','Property_id');
}
}
In my controller I am trying to get data as ,
$leads = PropertyLead::with('leadPropertyDetails','user','propertyRatings')
->get();
Here in $leads variable i am getting all the data that I want but In 'propertyRatings' I am getting user_id and other details. I also want to get the name user who rated that property using that user_id in propertyRatings object. I am really troubled in this query. Thanks in advance.
Use nested eager loading syntax to load nested relationships:
PropertyLead::with('propertyRatings', 'propertyRatings.user', 'leadPropertyDetails', 'user')->get();
Then you be able to display user name with:
#foreach ($leads as $lead)
#foreach ($lead->propertyRatings as $propertyRating)
{{ $propertyRatings->user->name }}
#endforeach
#endforeach
Suppose I have 3 tables, posts, post_images, and post_links.
post.id is a foreign key in both post_images and post_links.
Each post have multiple images.
I need a data which contains post, its images and its links as single element/array item. If there are 3 posts, I need 3 arrays with each array containing the posts images and links.
My code so far,
$data = DB::table('posts')
->join('post_images','posts.id' ,'=', 'post_images.post_id')
->join('post_links','posts.id' ,'=', 'post_links.post_id')
->select('posts.*')
->get();
with the above query I am getting all the records joined, If i have 3 records with 3 images each, I am getting 9 records, I just need 3 posts with its data as its sub arrays.
Any suggestion?
Here is the PostImage model
class PostImage extends Model
{
public function post() {
return $this->belongsTo(Post::class);
}
}
Here is the PostLink model
class PostLink extends Model
{
public function post() {
return $this->belongsTo(Post::class);
}
}
Here is the Post model
class Post extends Model
{
public function links() {
return $this->hasMany(PostLink::class);
}
public function images() {
return $this->hasMany(PostImage::class);
}
}
In the view you can reach everything you need.
#foreach ($posts as $post)
{$post->title} <br>
#foreach ($post->links as $link)
{$link->url} <br>
#endforeach
#foreach ($post->images as $image)
{$image->src} <br>
#endforeach
#endforeach
And if you want use less queries you could use eager loading to fetch all this data the first time. Eager Loading Laravel
Should look something like this
$posts = Post::with('images','links')->get();
if you already have relation in model you just have to use with method like
$data = PostModel::with('post_images','post_links')->get();
make it dd($data) and look at this. hope it will work.
References: https://laravel.com/docs/5.4/eloquent-relationships#eager-loading
I've got 3 tables, the users table, the image table, and the favorites table which works sort of like a pivot table, as all it has is ID, image_id, and user_id.
In my user model, I have:
public function FavoritedByMe() {
return $this->hasMany('CommendMe\Models\Favorite', 'user_id');
}
In my favorites controller, I have:
public function getFavorites($username) {
$user = User::where('username', $username)->first();
return view('user.favorites')
->with('user', $user);
}
and this works just fine if I want to get the IDs of all the images I've favorited:
#foreach ($user->FavoritedByMe as $favorite)
{{ $favorite->image_id }}
#endforeach
However, what I'd really like to be able to return the view with the images themselves. Something like:
$favImages = Images::where('id', $user->FavoritedByMe->image_id);
return view('user.favorites')
->with('user', $user)
->with('favImages', $favImages);
Now obviously this won't work, and will return the error:
ErrorException in FavoritesController.php line 54: Undefined property: Illuminate\Database\Eloquent\Collection::$image_id
but perhaps some kind of Eloquent relationship would? I've tried making those work but they just don't "click" in my head.
How could I make this work?
Thanks in advance!
In your Favorite model add this relationship:
public function image()
{
return $this->belongsTo('YourImageModel');
}
Then you can acces the image like this:
#foreach ($user->FavoritedImages as $favorite)
{{ $favorite->image->yourProperty }}
#endforeach
In the laravel's best practices you should call your FavoritedByMe relationship favorites since it's obviously related to the user.