简体   繁体   中英

Laravel query on one-to-many relationship

I have Post and Comment models. Post and Comment have one-to-many relationship, so one post can have many comments. Every comment has a user foreign field ( User and Comment have also one-to-many).

I want to get posts where a specific user commented on. We can assume that, a user could write a comment on a post only once.

You can use the Has Many Through relationship. The "has-many-through" relationship provides a convenient shortcut for accessing distant relations via an intermediate relation.

class User extends Model
{
    public function posts()
    {
        return $this->hasManyThrough('App\Post', 'App\Comment');
    }
}

Now you can get all posts where the user has commented by accessing this $user->posts

You can add additional relationship for Post and User models.

class User extends Model {
// add this to connect your user to your post through the comment 
// (assuming one to many relationship between Comment and Post is working well)
  public function posts()
  {
     return $this->hasManyThrough(Post::class, Comment::class);
  }
}

So you can get the posts that specific user has commented on with this $user->posts()->get()

You can read more about HasManyThrough here

Assuming that the Users in your app can create Posts as well comment on posts created by other users, you could have the relations as under:

The User Model

namespace App;

use App\Post;
use App\Comment;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function posts()
    {
        return $this->hasMany(Post::class);
    }

    public function comments()
    {
        return $this->hasMany(Comment::class);
    }

    public function commentedPosts()
    {
        $posts = Post::whereHas('comments', function ($query){
            $query->whereUserId($this->id);
        })->get();
        return $posts;
    }
}  

The Post Model

namespace App;

use App\Comment;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}

The Comment Model

namespace App;

use App\Post;
use App\User;
use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    public function post()
    {
        return $this->belongsTo(Post::class);
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

Then to get the Posts where the given User has commented you can use

$user->commentedPosts();

I think this can help you:

Post::whereHas('comments', function($q) use($userId){
$q->whereHas('user', function($qq) use ($userId)
{
    $qq->where('id',$userId);
}})->get();

When we loading related models we can use function whereHas if we want to filter query by related model. So here we have Post->Comment->User. And we want to make criteria by specific User. So in this example i pass two times variable $userId with keyword "use" so i can use it in inner closure. I also pass first variable $q with means its an comments query, so i can filter by any comments rule. And again i use same. 'comments' and 'user' has to be name of your relation function so if in your post model you have anything different from function comments to return comments with posts you should change 'comments' to your function name, also and for 'user'.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM