2014-06-26 60 views
1

我有一個直接的「項目」模型。一個項目可以有很多任務,每個任務都屬於一個員工。 我有一個頁面顯示+ - 100個項目,以及所有相關(獨特)員工。這導致500多個查詢被執行,所以頁面加載時間猛增到不可接受的水平。所以我給了急切的加載一個嘗試:Laravel 4.1 Eager正在加載工作,但查詢仍然在視圖中執行

$projects->with(array('tasks' => function($query) 
{ 
    $query->select('project_id', 'employee_id')->distinct()->get(); 
})); 

據我可以告訴通過調試,這給了我想要的結果。對於每個項目,都可以正確檢索任務,而不會有重複的員工。

但是,當我嘗試在視圖中加載任務時,Laravel仍然執行400多個查詢來檢索每個項目的任務。

@foreach ($projects as $project) 
    @foreach($project->tasks as $task) 
     @if($task->employee_id != 0) 
      <img src="{{UserHelper::getGravatarUrl($task->employee->id)}}" alt="{{{ $task->employee->name }}}" 
     @endif 
    @endforeach 
@endforeach 

我一直在使用tasks()tasks()->get()而不是嘗試過,但都無濟於事。我如何訪問急切加載的屬性? 我不喜歡使用髒原始查詢,因爲Eloquent應該完成任務。

回答

2

我要個位相加,以狼人的回答:

1)正確的方式來獲得你的對象是:

$projects->with(array('tasks' => function($query) 
{ 
    $query->select('project_id', 'employee_id')->distinct(); 
}))->get(); 

的get在外面,裏面沒有對預先加載。

2)你的函數的任務(在項目)應該有一個一對多的關係指向任務模型與外鍵由狼人提到

3)預先加載使您能夠加載N + 1時間提前一年至一年,例如,如果您需要引用內部項目的員工,以便能看到哪些任務去哪個員工,而不是運行

SELECT * FROM employee WHERE id = ? 
每個你爲了從獲取數據運行 $task->employee()->name

關係

所以急切的加載會SELECT * FROM employee第一 - 然後在任務內將急切加載在哪裏(?,?,?)(請糾正我,如果我錯了)

4)帶我到我的第4點將是以迫切的加載員工,這將減少查詢。建立一對多內部任務的功能關係。

+0

事實證明,即使在匿名函數中使用get(),渴望的加載仍然按預期工作。這是UserHelper多次檢索用戶。你的解釋很好,但是急切的裝載就是這樣。 – Maarten00

+0

@ Maarten00來自非熱切的加載框架和純SQL連接等 - 我知道它是如何感覺:) – azngunit81

0

您不能依靠select()工作,因爲Eloquent可能需要所有模型的屬性才能正確加載。要麼擺脫選擇或嘗試添加更多列到選擇語句。

2

據此,您的關係應該使用id字段的projects表和project_id字段的tasks表構建。還要確保你最後調用了get()方法。

您可以使用選擇的預先加載,但要確保你所選擇的關係建設者鍵,例如,如果你的Project有很多Tasktasks表包含project_idforeign key,那麼你需要選擇該外鍵select。所以請確保project_id可用tasks表中作爲foreign key建立與projects表的關係。例如,檢查:

$r = Role::with(['users' => function($q) { 
    $q->select('role_id', 'username'); 
}])->get(); 

我有一個包含role_id爲外鍵建立rolesusers表之間的關係,並已在Role模型宣佈one-to-many關係users表,所以我可以用select()躍躍欲試負載相關User型號(只有role_id和'用戶名'將在相關的User型號中加載),但select中沒有role_id我無法加載相關的User型號。

0

除了上面的答案之外,我還將添加自己的查詢,以便完美地加載每個項目的所有任務,以及員工和員工的配置文件。

$projects->with(array('tasks' => function($query) 
{ 
    $query->groupBy('project_id', 'employee_id')->with(array('employee.profiles')); 
})); 

我在我看來,這些訪問是這樣的:

@foreach($projects as $project)  
    @foreach($project->tasks as $task) 
     @if($task->employee_id != 0) 
      <img src="{{UserHelper::getGravatarUrl($task->employee)}}" alt="{{{ $task->employee->name }}}"> 
     @endif 
    @endforeach 
@endforeach 

這個偉大的工程,並大大降低了我的查詢量。

相關問題