简体   繁体   中英

Laravel hasMany as many hasOne

For example, i have Post and Comment models. When i load hasMany relation, i want to get separate parent item for each relation item.

Post.php:

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

Comment.php:

class Comment extends Model
{
    public function comments()
    {
        return $this->belongsTo('App\Post');
    }
}

When i load post with comments

Post::where('title', 'LIKE', search) 
    ->orWhereHas('comments', function ($query) use ($search) {
        $query->where('text', 'LIKE', $search) 
    })
    ->paginate();

results looks like this

[
    {
        post_id: 1,
        comments: [
            {
                comment_id: 1
                post_id: 1
            },
            {
                comment_id: 2
                post_id: 1
            },
            {
                comment_id: 3
                post_id: 1
            },
        ]
    },
    ...
]

but i need it to look like this (separate Post for each Comment).

[
    {
        post_id: 1,
        comments: [
            {
                comment_id: 1
                post_id: 1
            }
        ]
    },
    {
        post_id: 1,
        comments: [
            {
                comment_id: 2
                post_id: 1
            }
        ]
    },
    {
        post_id: 1,
        comments: [
            {
                comment_id: 3
                post_id: 1
            }
        ]
    },
    ...
]

Can i do it with Laravel?

You are now retrieving posts with their comments, but from what I understand you actually want to retrieve comments from specific posts.

The only difficulty then is specifying which posts to load the comments from, but this might do the trick:

$comments = Comment::whereHas('post', function($query) use ($ids) {
        $query->whereIn('post_id', $ids);
    })
    ->with('post')
    ->get();

(two small errors in the Comment model need to be fixed first: rename the function from comments() to post() and change this to $this )

Here's a simple foreach to test the result:

foreach ($comments as $comment) {
    echo 'Post ' . $comment->post->id . ' comment' . $comment->id . '<br>';
}

If you absolutely need the result in the format you show in the JSON data some extra work is needed, but it should not be necessary to do that to get the output as you show in the image you linked in the comments.

UPDATE (because the user changed the question):

Searching by comment text (instead of post-id) makes the query even easier; now no nested query is necessary at all:

$comments = Comment::where('text', 'like', '%' . $search . '%')
        ->with('post')
        ->get();

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