Thinkphp5基礎——07 模型(模型關聯——查詢篇)

TimChen666發表於2018-12-02

前言

有的時候,因為model對應的資料表有一些資料是從另外的表得來的。這種情況,我們就需要定義模型關聯關係。

常用的模型關聯關係分為一對一、一對多、多對多。

模型包含查詢、修改等操作,混合一起描述可能會比較亂,所以我將分開講述。


特別注意

一般來說,model類名會自動關聯同名的資料表,如果想要修改這個對應關係,可以這麼做:

protected $table = '表名';




一對一查詢

一對一有hasOne以及belongsTo兩種,那麼它們對應的使用場景是怎樣的呢?


先來看看官方文件:

hasOne('關聯模型','外來鍵','主鍵');

belongsTo('關聯模型','外來鍵','關聯主鍵');

這裡面,我們需要仔細看第三個引數

hasOne是主鍵,意味著本模型對應的表是主表,有一個從表通過外來鍵關聯本表(模型)的主鍵。

而belongsTo是關聯主鍵,意味著本模型對應的表是從表,本表(模型)通過本表(模型)的外來鍵關聯主表(模型)的主鍵。


總結:外來鍵在本表,使用belongsTo;反之,使用hasOne。



例子

商品表有外來鍵img_id,關聯著圖片表的id,

這時候在商品模型應該使用belongsTo關聯圖片模型,因為外來鍵在本表;

而如果圖片模型想關聯商品模型,應該使用hasOne,因為外來鍵在商品表。







hasOne

hasOne('關聯模型','外來鍵','主鍵');

我們用程式碼實現一下上面的例子
	
	class Img
	{
	  // 定義關聯方法,名字隨意
	  public function product()
	  {
	    $this->hasOne('Product', 'img_id', 'id');
	  }
	}





belongsTo

belongsTo('關聯模型','外來鍵','關聯主鍵');

	
	class Product
	{
	  // 定義關聯方法,名字隨意
	  public function img()
	  {
	    $this->belongsTo('Img', 'img_id', 'id');
	  }
	}





一對多查詢

一對多隻有一種方法,hasMany。

hasMany('關聯模型','外來鍵','主鍵');



例子

假設文章下有多個評論,評論通過art_id關聯文章的id。


class Article extends Model 
{
	public function comments()
	{
	  return $this->hasMany('Comment','art_id','id');
	}
}





多對多查詢

belongsToMany('關聯模型','中間表','外來鍵','關聯鍵');
  • 外來鍵:中間表的當前模型外來鍵,預設的外來鍵名規則是關聯模型名+_id
  • 關聯鍵:中間表的當前模型關聯鍵名,預設規則是當前模型名+_id



例子

假設分類下有多個商品,商品也可以屬於多個分類,就需要使用多對多查詢了。


class Theme extends model
{
	// 關聯product表
	public function products(){
        return $this->belongsToMany('Product','theme_product','product_id','theme_id');
	}
}






關聯預載入

關聯查詢的預查詢載入功能,主要解決了N+1次查詢的問題

譬如如下語句,最終會執行4次查詢。

$list = User::all([1,2,3]);

而使用了關聯查詢,就可以變成2次查詢。
$list = User::with('profile')->select([1,2,3]);



使用方法

with()



基礎例子


	1. 預載入單個模型
	$list = User::with('profile')->select([1,2,3]);


	2. 預載入多個模型(陣列形式)
	$list = User::with(['profile','book'])->select([1,2,3]);






巢狀關聯

譬如一個banner對應多個banner_item,一個banner_item對應一個img。

我們需要先關聯banner_item,再關聯img。


簡單例子


class Banner extends model
{
 
	// 查詢banner_item的資訊
	public static function getBannerByID($id){
	  $banner = self::with('items.img')->find($id);
	  return $banner;
	}


	// 關聯banner_item表
	public function items(){
	  return $this->hasMany('BannerItem','banner_id','id');
	}
}



class BannerItem extends model
{
	// 關聯Image表
	public function img(){
	  return $this->belongsTo('Image','img_id','id');
	}
}


getBannerByID方法裡面巢狀關聯了img模型,

它先是關聯了bannerItem,然後通過bannerItem模型的img方法關聯到img模型。






閉包式寫法

不難理解,直接上程式碼。


$list = User::field('id,name')->with(['profile'=>function($query){
	$query->field('user_id,email,phone');
}])->select([1,2,3]);






延遲預載入

有些情況下,需要根據查詢出來的資料來決定是否需要使用關聯預載入。

注意,這個適合多資料查詢。

直接上程式碼。


// 查詢資料集
$list = User::all([1,2,3]);

// 延遲預載入
$list->load('cards');

相關文章