2016-06-09 2 views
3

다음은 모두 Discussionsthreadsposts을 가져와야하는 코드입니다. 게시물의 수를 1로 제한하려고합니다.이 작업을 수행 할 때 각 스레드마다 1 개의 게시물 만 있으면되지만 9 개의 스레드에는 게시물이없고 1 개의 스레드에는 1 개의 게시물이 있습니다.Laravel : 중첩 된 관계 제한

App\Discussion::with([ 
    'threads' => function ($query) => { 
     // Correctly limits the number of threads to 10. 
     $query->latest()->take(10); 
    }, 
    'threads.posts' => function ($query) { 
     // Limits all posts to 1, not each post to 1 for each thread. 
     $query->take(1); 
    } 
])->where(['slug' => 'something'])->firstOrFail(); 

위의 코드는 데이터베이스에서 다음과 같은 SQL 쿼리를 실행합니다.

select * from `discussions` where (`slug` = ?) and `discussions`.`deleted_at` is null limit 1 

select * from `threads` where `threads`.`discussion_id` in (?) and `threads`.`deleted_at` is null order by `created_at` desc limit 10 

select * from `posts` where `posts`.`thread_id` in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) and `posts`.`deleted_at` is null order by `created_at` desc limit 1 

나는 세 번째 쿼리를 볼 수는 1. 나는 다음을 볼 것으로 예상

에 모든 게시물 제한됩니다으로 문제를 일으키는 하나입니다; 하나의 토론, 10 개의 스레드와 1 개의 게시물이 해당 스레드에 있습니다.

{ 
    "id": 1, 
    "title": "Discussion Title", 
    ... 
    "threads": [ 
    { 
     "id": 1, 
     "title": "Thread Title", 
     ... 
     "posts": [ 
     { 
      "id": 1, 
      "title": "Post Title", 
      ... 
     } 
     ] 
    } 
    ... 
    ] 
} 

Laravel 프레임 워크에서이를 수행 할 방법이 있습니까, 아니면 원시 쿼리를 실행해야합니까? Eloquent ORM을 가능한 한 많이 사용하고 싶습니다.

+0

스레드 모델 코드, 구체적으로 "public function posts()"를 표시하십시오. 그것은 다 대다 또는 일대 다 관계입니까? –

답변

2

Eloquent는 숫자 결과를 제한하는 쿼리 방법이 없으므로 몇 가지 "조정"을해야합니다.

먼저이 함수를 스레드 모델에 만듭니다.

public function one_post() 
{ 
    //OrderBy is optional 
    return $this->hasOne(Post::class)->orderBy('id', 'asc'); 
} 

이제는 하나의 게시물 만 반환하는 관계가 있습니다. 당신은 당신의 질문이 방법이있을 수 있습니다

App\Discussion::with([ 
     'threads' => function ($query) { 
      // Correctly limits the number of threads to 10. 
      $query 
       ->latest() 
       ->take(10) 
       ->with('one_post'); 
     } 
     ])->where(['slug' => 'something'])->firstOrFail(); 
+2

시도해 보셨습니까? 토론 당 10 개의 스레드가 아니라 총 10 개의 스레드를 반환 할 것으로 예상됩니다. 이 내부 쿼리는 한 번만 실행해야합니다. Eloquent는 하나의 쿼리를 수행하여 모든 토론을 가져오고 하나의 쿼리를 통해 모든 스레드를 얻습니다. 따라서 두 번째 쿼리를 10 개만 수정하면 모든 쿼리가 10 개가됩니다. – jfadich

+1

@jfadich이 쿼리는 "slug"가 "something"인 첫 번째 토론을 반환합니다. 10 개의 최신 스레드가 관계로로드됩니다. 각 스레드에는 하나의 관계가 관계로로드됩니다. –

+0

네 말이 맞아, 나는 실수로 토론의 모음이 아니라, 하나의 토론이라고 생각했다. 내가 놓친 것은'firstOrFail()'이었고'get()'이 아니었다. – jfadich

1

열망 결과를 쉽게 제한 할 수 없지만에 따라 :

: 코드가 같은 것을 볼 수 있었다 즉 .... https://laracasts.com/discuss/channels/eloquent/laravel-51-eloquent-relationship-hasmany-limit-records하는 모델 관계를 사용하여 매핑 할 수 있습니다
App\Discussion::with([ 
     'threads' => function ($query) => { 
      // Correctly limits the number of threads to 10. 
      $query->latest()->take(10); 
     }])->where(['slug' => 'something'])->firstOrFail() 
     ->map(function ($thread) { 
      $thread->setRelation('posts', $thread->posts->take(1)); 
      return $thread; 
     });