Eloquent access list of models via models - php

A User has many Auktion and Gebot.
A Gebot belongs to one Auktion and one User
I want to fetch all Auktion where the User also has a Gebot
Something like:
Auth::user()->gebote->auktionen->orderBy('end_time');
The orderBy() should be executed on the Auktionen retreived via Gebot, which is not possible because the relationship between Auktion and Gebot is one-to-many:
**Gebot Model**
public function auktion()
{
return $this->belongsTo('App\Auktion');
}
public function user()
{
return $this->belongsTo('App\User');
}
**Auktion Model**
public function gebote()
{
return $this->hasMany('App\Gebot', 'auktion_id');
}
public function user()
{
return $this->belongsTo('App\User');
}
What is the proper relationshsip setup and query to achieve this?
EDIT:
My current approach is this
#foreach (Auth::user()->gebote as $gebot)
<?php $auktion = $gebot->auktion;
if($auktion->anzeigentyp_id == 2)
continue; ?>
#include('shop/row')
#endforeach
which is not very clean as I am fetching all entries first and I can't orderBy()

Use whereHas() which will filter your relation by it's subrelation. Auktion must have relation smth like hasMany() to gebots
$userId = Auth::user()->getKey();
App\Auktion::whereHas('gebot', function ($query) use($userId) {
//here you need to filter gebots which belongs to user
$query->where('user_id', $userId);
})->orderBy('end_time')->get();

Related

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');
}

Multiple relations (pivot) in Laravel

I have a problem with related models.
There are three models. User, PostType (music, animals) and Post.
A user can select the posttypes he wants to see. So I created a pivot-table posttype_user.
Now I can save the selected postTypes binded to a user.
// User model
public function postTypes()
{
return $this->belongsToMany(PostType::class);
}
// PostType model
public function users()
{
return $this->belongsToMany(User::class);
}
The Post model has a foreign key with postType_id. And this relationships in the models:
// Post model
public function postType()
{
return $this->belongsTo(PostType::class);
}
// PostType model
public function post()
{
return $this->hasMany(Post::class);
}
Now I want to receive all Posts (of the selected posTypes) from the current user (Auth::user()).
But I don't know how. Does anyone have an idea?
You can use nested whereHas():
Post::whereHas('postType', function($q) {
$q->whereHas('users', function($q) {
$q->where('id', auth()->id());
});
})->get();
Or you can do this:
$postTypeIds = auth()->user()->postTypes()->pluck('id');
$posts = Post::whereIn('post_type_id', $postTypeIds)->get();

Laravel - Eloquent: get posts from user with users post table

I searched a lot but could not find any answer about it, so I hope you could help me!
I have three tables: posts, users and post_users.
Post_users contains two columns: user_id and post_id.
I need to get all posts by an user with Eloquent. Any ideas?
Model User:
public function posts()
{
return $this->belongsToMany('App\Post', 'post_users', 'user_id', 'post_id');
}
Model Post:
public function users()
{
return $this->belongsToMany('App\User', 'post_users', 'post_id', 'user_id');
}
Try:
$user = User::find($id);
$allpost = $user->posts()->get();
var_dump($allpost);
The Laravel docs cover this pretty well but I had an issue with it when I first started as well. Check out Laravel Relationships for the fully write up.
// Inside your Post model
public function user() {
return $this->belongsTo('App\User');
}
// Inside your User model
public function posts() {
return $this->hasMany('App\Posts');
}
You can then create a query:
$posts = User::find(1)->posts;
Or you can filter it further..
$posts = User::find(1)->posts()->where('active', 1)->get();
You may need to change your paths for the hasMany() and belongsTo() if your model location and names are different.
As you wish. Relation between User and Post is many-to-many
- Defined relation
// In User model
public function posts(){
return $this->belongsToMany(Post::class);
}
// In Post model
public function users(){
return $this->belongsToMany(User::class);
}
- Table structure
- users
id
- posts
id
- post_user
user_id
post_id
- Get all post by a user
$posts = User::find($user_id)->posts
If you donot have relationship built, try this. However building relationships is preferred. PostUsers and Posts are assumed models of post-users and posts tables, and post as column of the posts table. this gives the posts of logged in user, but not tested.
$postusers=PostUsers::where(['user_id'=>Auth::user()->id])->get();
foreach($postusers as $postuser)
{
$posts=Posts::where(['post_id'=>$postuser->post_id)]->get();
foreach($posts as $post)
{
print_r($post->post);
}
}
Try this
From Controller :
dd(Auth::user()->posts);
App/User
public function posts()
{
return $this->belongsToMany('App\Entities\posts', 'post_users', 'user_id', 'post_id');
}
make relationship with post model on the user model:
public function posts()
{
return $this->hasMany(Post::class);
}
make relationship with user model on the post model:
public function User()
{
return $this->belongsTo(User::class);
}
in controller or Wherever you use:
$userPosts = User::find($user->id)->posts->where('status', 1);

Eloquent many-to-many-to-many - how to load distant relation easily

I have 3 tables; users, groups and permissions
In models I have the relationships set as belongsToMany
in user model:
public function groups() {
return $this->belongsToMany('Group');
}
in group model:
public function users() {
return $this->belongsToMany('User');
}
public function permissions() {
return $this->belongsToMany('Permission');
}
in permissions model:
public function groups() {
return $this->belongsToMany('Group', 'id');
}
many users - to - many groups
many groups - to - many permissions
I'm trying to get all the permissions a user has, and have no clue what the code for it should look like. Can anyone help?
This is how you can do it:
User::where('id', $id)->with(['groups.permissions' => function ($q) use (&$permissions) {
$permissions = $q->get()->unique();
}])->first();
// then
$permissions; // collection of unique permissions of the user with id = $id
It should look something like this if you are eager loading...
$user = User::where('id', $id)->with(['groups.permissions'])->first();

Categories