2016-11-22 87 views
3

在我Laravel應用程序,我在模型(ModelA),而利用的SQL_CALC_FOUND_ROWS,然後進行事後SELECT FOUND_ROWS()做一個普通的查詢檢索的所有記錄的計數因爲第一個查詢使用LIMITOFFSETLaravel - 使用`SQL_CALC_FOUND_ROWS`與渴望加載關係返回錯誤計數

這工作得很好,但現在我已經添加了一個關係到我上面查詢的模型,如果我做同樣的查詢但使用with->('modelB'),這個查詢是在初始查詢之後和SELECT FOUND_ROWS()之前執行的,所以我得到正如我期待的那樣,ModelB結果的計數而不是ModelA

有沒有辦法讓這項工作按照需要在哪裏我得到的第一個(主)查詢的計數,而不是關係?

例如這工作得很好:

$query = ModelA::select([DB::raw("SQL_CALC_FOUND_ROWS *")]) 
    ->where('active', 1); 

// conditional ->where()'s 

$query->skip(intval($skip)) 
    ->take(intval($take)) 
    ->orderBy($column, $dir); 

$results = $query->get(); 

$total = DB::select(DB::raw("SELECT FOUND_ROWS() AS 'total';"))[0]->total; 

但改變第一線,這並不:

$query = ModelA::with('modelB') 
    ->select([DB::raw("SQL_CALC_FOUND_ROWS *")]) 
    ->where('active', 1); 

一種解決方法是僅僅做沒有急於加載和單獨提取每個關係,但後來我想當我在代碼中稍後循環結果時,每個結果都有一個查詢。

回答

2

通過FOUND_ROWS()可獲得的行計數是暫時的,無意超過SELECT SQL_CALC_FOUND_ROWS聲明後面的語句。如果您稍後需要參考該值,則將其保存...

Eloquent's eager loading將導致爲with方法中的每個關係執行額外的選擇語句。

因此FOUND_ROWS()返回最後一個SELECT聲明的計數,該聲明是熱切加載的關係。

爲了解決這個問題,你可以使用lazy eager loading。相反的:

$books = App\Book::with('author.contacts')->get(); 

用途:

$books = App\Book::all(); 
$count = DB::select(DB::raw('SELECT FOUND_ROWS()')); 
$books->load('author.contacts'); 
+0

從來沒有想到這一點,我認爲這可能是最簡單的方法。謝謝! – martincarlin87

1

ModelA::with('modelB')導致2個基礎表中的join。如果modelB中有多個記錄對應於modelA中的單個記錄,則查詢返回的記錄數可能會多於modelA中的記錄數。 SQL_CALC_FOUND_ROWS返回整個查詢中的記錄數,您不能將其限制爲查詢中的單個表。

您可以單獨計算modelA個記錄並返回該數字,或者您需要從modelA的表中選擇子查詢中包含的SQL_CALC_FOUND_ROWS中的數據。我會去單獨計數。它很直接簡單。

+0

我不認爲這是做加盟,'with'似乎是在做一個'WHERE IN'找到其他記錄第一個表相關。這是一對一的,如果這有幫助的話,但我希望在第二個查詢開始之前可能有某種回調或類似的使用'SQL_CALC_FOUND_ROWS *'。我認爲你是對的,一個查詢計數會比每個結果沒有急切加載更好。 – martincarlin87