2017-02-12 59 views
0

我有一個相對簡單的數據庫結構,包括國家,地區和倉庫。每個車廠被分配給運營商和區域:Laravel/Eloquent:限制嵌套的熱切負載,以免包含空父母


運營商

+----+------------+ 
| ID | name | 
+----+------------+ 
| 1 | Operator 1 | 
| 2 | Operator 2 | 
+----+------------+ 

國家

+----+----------------+------+ 
| ID | country_id | code | 
+----+----------------+------+ 
| 1 | United Kingdom | gb | 
| 2 | France   | fr | 
+----+----------------+------+ 

地區

+----+-----------------+-------+ 
| ID | country_id (FK) | name | 
+----+-----------------+-------+ 
| 1 |    1 | North | 
| 2 |    1 | South | 
| 3 |    1 | East | 
| 4 |    1 | West | 
| 5 |    2 | North | 
| 6 |    2 | South | 
| 7 |    2 | East | 
| 8 |    2 | West | 
+----+-----------------+-------+ 

+----+----------------+------------------+-----------+ 
| ID | region_id (FK) | operator_id (FK) | name | 
+----+----------------+------------------+-----------+ 
| 1 |    1 |    1 | Newcastle | 
| 2 |    8 |    2 | Nantes | 
+----+----------------+------------------+-----------+ 

我已經在各自的車型成功地建立了自己的口才關係。

我想加載每個倉庫分組到各自的地區和國家,並通過特定的運營商進行過濾。

$depots = Country::with('regions.depots')->whereHas('regions.depots', function($query) use ($opID) { 
    $query->where('operator_id',$opID); 
})->get(); 

這是卓有成效的,但還有預先加載的軟件倉庫,這也是預先加載所有地區,包括那些沒有分配給他們的倉庫。例如。當上述執行時$opID = 1,你會得到這樣的結果:

name: United Kingdom, 
regions: [ 
    { 
     name: North, 
     depots: [{ 
      name: Newcastle 
     }] 
    }, { 
     name: South, 
     depots: [] 
    }, { 
     name: East, 
     depots: [] 
    }, { 
     name: West, 
     depots: [] 
    } 
] 

我想是上述返回,但沒有那裏沒有倉庫的區域。

我玩過withwhereHas的限制,但無法獲得所需的數據結構。爲什麼下面的代碼沒有達到預期的效果?

$depots = Country::with(['regions.depots' => function($query) use ($opID) { 
    $query->where('depots.operator_id',$opID); 
}])->get(); 

如果孩子不存在,是否有任何方法不急於加載父項?或者是我執行上述查詢,然後手動循環查看結果的情況?


編輯

於是幾個小時後,我終於找到一個辦法讓我想要的結果。但它看起來很髒。這真的是最好的方法嗎?

$depots = Country::whereHas('regions.depots', function($q) use ($opID) { 
    $q->where('operator_id',$opID); 
})->with(['regions' => function($q) use ($opID) { 
    $q->with('depots')->whereHas('depots', function($q2) use ($opID) { 
     $q2->where('operator_id',$opID); 
    }); 
}])->get(); 

EDIT 2

因此,原來第一個編輯竟是上的一切,但depots表,我添加了由另一家運營商擁有的另一蓄積其儘快意味着查詢operator_id在同一地區,當我不想要它的時候就會出現。下面看起來更混亂,但確實有效。這是跟自個兒說話樂趣;)希望這可以幫助別人第一天開始...

$depots = Country::has('regions.depots') 
      ->with(['regions' => function($q) use ($opID) { 
       $q->with(['depots' => function($q2) use ($opID) { 
        $q2->where('operator_id',$opID); 
       }])->has('depots'); 
      }])->get(); 

回答

0

您可以隨時使用延遲加載:

$depots = Country::whereHas('regions.depots', function($q) use ($opID) { 
    $q->where('operator_id',$opID); 
})->get()->load('regions.depots'); 
+0

謝謝,但這個似乎有相同的結果。我最初的代碼塊 – Ian