簡體   English   中英

Laravel 5如何使用鏈接檢索相關的表數據

[英]Laravel 5 How to retrieve related table data using chaining

我有地區(城市列表),租賃(租賃信息列表)和Rental_Location(租賃地址列表+緯度/長)的數據庫表。

基本關系是:

Regions haveMany Rentals (with FK's region_id and rental_location_id in Rentals table)
Locations haveMany Rentals, or the reverse logic Rental belongsTo a Location

我想要做的是從region_id(來自租賃表)獲取區域中所有租賃的位置信息,以及包括位置空間數據(rental_locations表):

$region = Region::find(1);
$rentals = $region->rentals; // doesn't contain location information yet
$rentalDataWithSpatialLocationData = $region->rentals->location; // what I liked to do 

但是使用belongsTo關系的最后一行將無法通過將rental_locations中的空間數據添加到原始租賃集合中。

現在$ rental集合包含一個區域的所有租賃,但沒有空間數據來標記地圖上的位置,但除了在QueryBuilder中使用如下所示的連接而不在我的模型中使用ORM hasMany屬性:

$spatials = DB::table('rentals')
              ->join('regions', 'rentals.region_id', '=', 'regions.id')
              ->join('rental_locations', 'rentals.rental_location_id', '=', 'rental_locations.id')
              ->where('rentals.region_id', '=', $region_id)
              ->select('*')
              ->get();

基本上,我無法弄清楚如何使用其位置信息獲取所有租賃的集合,這是否可以使用ORM? 看起來這樣比連接可能會變得昂貴,所以我現在假設您不使用ORM來排除QueryBuilder,而只是補充簡單和快速的關系查詢?

這里有幾件你應該知道的事情。

首先,對於您的原始問題,您的代碼將無法運行,因為您嘗試訪問租賃模型Collection上的關系屬性,而不是單個模型。 如果您遍歷Collection ,您將能夠很好地訪問每個單獨項目上的location關系:

$region = Region::find(1);
$rentals = $region->rentals; // Collection of rentals for the region
foreach($rentals as $rental) {
    print_r($rental->location); // location info for the individual rental
}

現在,有關上述代碼的一點需要注意的是,您將遇到所謂的N + 1問題。 默認情況下,Laravel延遲加載關系對象,因此在需要關系屬性之前,不會運行填充關系數據的查詢。 暫時忽略該區域,在上面的代碼中,Laravel將運行一個查詢以獲取所有租借,然后在foreach循環中,它將為每個循環迭代(N個查詢)運行新查詢以獲取位置信息每次出租; 因此N + 1個查詢。

要緩解此問題,您可以急切加載關系。 通過急切加載,Laravel將運行一個查詢來獲取租金,然后運行一個查詢以獲取所有租賃的所有位置信息,總共兩個查詢(而不是N + 1)。 將區域信息重新放回那里,實際上是三個查詢。

要急切加載關系,可以在查詢中使用with()方法:

// eager load the rentals, and the nested location on the rentals
// 1 query for region, 1 for all rentals on region, and 1 for all locations on rentals
$region = Region::with('rentals', 'rentals.location')->find(1);

// this is now accessing already loaded rentals; no lazy loading needed
$rentals = $region->rentals;

foreach($rentals as $rental) {
    // this is now accessing already loaded locations; no lazy loading needed
    print_r($rental->location);
}

這樣做的另一個不同之處是,您可能認為自己無法訪問位置信息,因為延遲加載的關系在您訪問它們之前不會顯示,而急切加載的關系立即可用。 通過將對象打印到屏幕進行調試時,這可能會讓您認為當您真的沒有時會丟失數據。 我的意思是:

/**
 * lazy load relationships
 * This will only show the information for the region object. No
 * rental or location information will be shown as it has not been
 * loaded yet.
 */
$region = Region::find(1);
print_r($region);

/**
 * eager load relationships
 * This will show the information for the region object, as well as
 * all of the related rental objects and their related location
 * information.
 */
$region = Region::with('rentals', 'rentals.location')->find(1);
print_r($region);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM