Laravel 模型關聯、關聯查詢、預加載使用實例


數據表通常相互關聯,通常簡單一些的可以使用多表聯查進行查詢,對於更加復雜的使用laravel的模型關聯查詢更加方便簡單,中文文檔,下面以省市兩張表為例

前期准備:

首先創建一個PlaceController控制器並創建index方法:

<?php

namespace App\Http\Controllers\Api;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class PlaceController extends Controller
{
    public function index(Request $request)
    {

    }
}

然后創建分別創建省市兩個模型(model):

<?php
namespace App\Http\Models;
use Illuminate\Database\Eloquent\Model;

class Province extends Model
{
    protected $table = 'province';

    protected $primaryKey = 'id';

    public $timestamps = false;
}
<?php
namespace App\Http\Models;
use Illuminate\Database\Eloquent\Model;

class City extends Model
{
    protected $table = 'city';

    protected $primaryKey = 'id';

    public $timestamps = false;
}

准備工作結束,要使用模型關聯必須先定義關聯關系即在模型中定義關聯方法。

一對一 :hasOne()

在Province模型中定義與City模型的關聯關系city():

    public function city()
    {
        return $this->hasOne('App\Http\Models\City', 'pid', 'id'); //參數一:需要關聯的子表類名,前面必須加上命名空間  參數二:子表關聯父表的字段  參數三:父表關聯子表的字段
    }

在PlaceController控制器的index()中使用:

    public function index(Request $request)
    {
        $place = Province::select('*')
            ->with(['city' => function($query) {  //city對應上面province模型中定義的city方法名  閉包內是子查詢
                return $query->select('*');
            }])
            ->where('id', 11)->first()->toArray(); //查詢id為11的省份及該省份下的第一個城市
        dd($place);
    }
array:3 [▼
  "id" => 11
  "pname" => "浙江省"
  "city" => array:3 [▼
    "id" => 89
    "pid" => 11
    "cname" => "台州市"
  ]
]

 除此之外,在子查詢語句中常規的where、orderBy等方法都可以使用:

    public function index(Request $request)
    {
        $cid = 99;
        $place = Province::select('*')
            ->with(['city' => function($query) use ($cid) { //傳參使用use() 多個參數($cid, $name)
                return $query->select('*')->where('id', $cid);
            }])
            ->where('id', 11)->first()->toArray();
        dd($place);
    }
array:3 [▼
  "id" => 11
  "pname" => "浙江省"
  "city" => array:3 [▼
    "id" => 99
    "pid" => 11
    "cname" => "杭州市"
  ]
]

 一對一定義反向關聯:belongsTo()

上面是從省份查下面的城市,反向關聯就是從城市查所屬身份,首先在city模型中定時province():

    public function province()
    {
        return $this->belongsTo('App\Http\Models\Province', 'pid', 'id'); //參數一:需要關聯的父表類名,前面必須加上命名空間  注意:參數二:子表關聯父表的字段 參數三:父表關聯子表的字段
    }

在控制器中使用:

    public function index(Request $request)
    {
        $place = City::select('*')
            ->with(['province' => function($query) {
                return $query->select('*');
            }])
            ->where('id', 99)->first()->toArray();
        dd($place);
    }
array:4 [▼
  "id" => 99
  "pid" => 11
  "cname" => "杭州市"
  "province" => array:2 [▼
    "id" => 11
    "pname" => "浙江省"
  ]
]

一對多:hasMany()

在province模型中定義citys():

    public function citys()
    {
        return $this->hasMany('App\Http\Models\City', 'pid', 'id');
    }

在控制器中使用:

    public function index(Request $request)
    {
        $place = Province::select('*')
            ->with(['citys' => function($query) {
                return $query->select('*');
            }])
            ->where('id', 11)->first()->toArray(); //查詢id為11的省份及該省下所有的城市
        dd($place);
    }
array:3 [▼
  "id" => 11
  "pname" => "浙江省"
  "citys" => array:11 [▼
    0 => array:3 [▼
      "id" => 89
      "pid" => 11
      "cname" => "台州市"
    ]
    1 => array:3 [▶]
    2 => array:3 [▶]
    3 => array:3 [▶]
    4 => array:3 [▶]
    5 => array:3 [▶]
    6 => array:3 [▶]
    7 => array:3 [▶]
    8 => array:3 [▶]
    9 => array:3 [▶]
    10 => array:3 [▶]
  ]
]

一對多反向關聯:belongsTo()

    public function provinces()
    {
        return $this->belongsTo('App\Http\Models\Province', 'pid', 'id'); //參數一:需要關聯的父表類名,前面必須加上命名空間  注意:參數二:子表關聯父表的字段 參數三:父表關聯子表的字段
    }

和一對一的反向關聯相同就不多說了

多對多:belongsToMany()

多對多比上面的都要復雜一些,需要用三張表演示,如role(角色表)role_authority(角色對應的權限表) 和 authority(所有權限表),其中role表(爺爺級)和role_authority(父級中間表)表的關聯字段是role_id, role_authority(父級中間表)表和authority(孫子級)表關聯的字段是authority_id, 那么就可以在role(爺爺級)表中定義關聯關系了:

    public function role()
    {
        return $this->belongsToMany('App\Http\Models\AdminAuthority', 'admin_role_authority', 'role_id', 'authority_id'); //參數一:最低一級的表類名(孫子級)  參數二:中間表(父級)的表名  參數三:中間表與他的父級表的關聯字段  參數四:中間表與他的兒子級表的關聯字段
    }
        $role = AdminRole::select('*')
            ->with(['role' => function($query) {
                return $query->select('*');
            }])
            ->where('role_id', 22)->first()->toArray();
        dd($role);
array:4 [▼
  "role_id" => 22
  "role_name" => "廣告設計師"
  "description" => "廣告設計"
  "role" => array:7 [▼
    0 => array:11 [▼
      "authority_id" => 88
      "name" => "廣告管理"
      "is_active" => 1
      "controller" => null
      "action" => null
      "url" => null
      "icon" => "Hui-iconfont-dangan"
      "parent_id" => 0
      "sort" => 3
      "role_id" => 22
      "pivot" => array:2 [▼
        "role_id" => 22
        "authority_id" => 88
      ]
    ]
    1 => array:11 [▶]
    2 => array:11 [▶]
    3 => array:11 [▶]
    4 => array:11 [▶]
    5 => array:11 [▶]
    6 => array:11 [▶]
  ]
]

敲黑板划重點:

1.關聯模型查詢的實質總共執行兩條SQL語句,打印一下執行的SQL語句:

        DB::connection()->enableQueryLog();#開啟執行日志
        $role = AdminRole::select('*')
            ->with(['role' => function($query) {
                return $query->select('*');
            }])
            ->where('role_id', 22)->first()->toArray();
        dd(DB::getQueryLog());   //獲取查詢語句、參數和執行時間
array:2 [▼
  0 => array:3 [▼
    "query" => "select * from `admin_role` where `role_id` = ? limit 1"
    "bindings" => array:1 [▼
      0 => 22
    ]
    "time" => 48.82
  ]
  1 => array:3 [▼
    "query" => "select *, `admin_role_authority`.`role_id` as `pivot_role_id`, `admin_role_authority`.`authority_id` as `pivot_authority_id` from `admin_authority` inner join `admin_role_authority` on `admin_authority`.`authority_id` = `admin_role_authority`.`authority_id` where `admin_role_authority`.`role_id` in (22) ◀"
    "bindings" => []
    "time" => 9.41
  ]
]

2.在關聯查詢中,select()如果不是查出全部字段,要查詢的字段必須包含表和表之間的關聯字段才可以使用:

$role = User::select('id', 'name')  //主表關聯字段是id
->with(['role' => function($query) {
return $query->select('user_id', 'name'); //子表關聯字段是user_id
}])
->first()->toArray();

3.另外還可以組合更加復雜的查詢,如三張表A、B、C,A表和B表一對一,A表和C表一對多,就可以使用leftjoin加關聯模型一對多查詢:

    public function items() {
        return $this->hasMany('App\Http\Models\A', 'aid', 'id');
    }
MallOrder::from('A as a')
      ->leftJoin('B as b','a.id','=','b.aid')
      ->with(['items' => function($query) {
          return $query->select('*');
      }])->group()->select('*');

類似上面的組合需要打開腦洞去想去實踐了,模型關聯查詢越用越順手,越用越覺得好用,簡直是居家旅行,裝B神器!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM