2016-06-09 165 views
3

以下是我必須提取所有Discussions及相關聯的threadsposts的代碼。我試圖限制帖子的數量爲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框架內執行此操作,還是需要運行原始查詢?我寧願儘可能地堅持雄辯的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個線程。該內部查詢應該只執行一次。雄辯會做一個查詢來獲得所有的討論,然後一個查詢來獲得所有的線程。所以如果你修改第二個查詢只需要10個,那麼對於所有事物來說只會得到10個。 – jfadich

+1

@jfadich這個查詢將返回第一個討論,其中「slug」是「某些東西」,10個最新的線程被加載爲關係。每個線程將有1個帖子作爲關係加載。 –

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