Laravel中的Eloquent(ORM)的工作方式很令人驚訝,並提供訪問數據庫的非常簡單的方法。在本文中,我們將瞭解Laravel Eloquent中的懶加載和即時加載以及它如何在後台運行。
Eloquent 中的關係
第一步我們需要定義模型之間的關係的。在這個例子中,我將使用兩個模型,house 和 city。房子屬於一個城市,城市有很多房屋。讓我們看看模型 House 的關係:
class House extends Model
{
protected $fillable = [
'title', 'description', 'price'
];
public function city() {
return $this->belongsTo('App\City');
}
}
注意:對於多對一的關係(房子屬於一個城市),函數名稱是單數。 [public function city()]
class City extends Model
{
protected $fillable = [
'name', 'code'
];
public function houses() {
return $this->hasMany('App\House');
}
}
注意:對於一對多關係(城市有很多房屋),函數名稱是複數。 [public function houses()]
懶加載
$houses = House::all();
默認情況下,在Eloquent中訪問數據是“懶加載”,在上面的代碼中,我們獲取了所有數據在內部表中,實際執行的SQL查詢是:
select * from `houses`
在這一步中,關係表(城市)中的數據還沒有被獲取,如果我們想訪問關係表中的數據,我們可以像這樣訪問:
foreach ($houses as $house) {
echo $house->city->name; // 這就是懶加載
}
實際執行的SQL查詢是
select * from `cities` where `cities`.`id` = ? limit 1
select * from `cities` where `cities`.`id` = ? limit 1
select * from `cities` where `cities`.`id` = ? limit 1
...
該過程將循環房屋內的所有記錄,併為每個循環執行1次查詢以獲取城市數據,例如我們有20個房屋記錄,查詢獲取關係表中的數據將執行20次+1原始查詢獲取 房屋數據,查詢“延遲加載”的時間是N + 1。
即時加載
有時在應用程序中使用即時加載非常有用,例如,你正在使用Ajax調用數據,在這種情況下,我們必須使用預加載來準備在關係表中包含數據的所有數據,然後再將結果返回給Ajax。 要使用即時加載,只需在獲取數據時使用 with 方法。
$houses = House::with('city')->get();
現在所有的房屋數據和在關係表中的數據都同時加載出來了,查詢的SQL語句的是
select * from houses
select * from cities where id in (1, 2, 3, 4, 5, ...)
使用即時加載時僅執行2個查詢。 正如你可以看到上面的查詢,一個查詢是在房屋表中獲取所有數據,另一個查詢是獲取城市表中的所有數據,使用IN操作將ID與房屋表中的city_id匹配。
懶加載 和 即時加載
在某些情況下,這對於即時動態加載非常有用,我們可以決定是否需要加載關係表中的數據。
$houses = House::all();
if($isLoad) {
$houses->load('city'); // 對應 house model中的 city 方法
}
我們可以使用 load 方法在特定條件下加載關係表中的數據。
這一點非常有用,實際中大家可以多試試。
總結
現在你理解了這個過程,希望它能幫助你理解懶加載和即時加載的用法和基本原理。
更多PHP知識,可以前往PHPCasts