目录
- [Laravel DB门面和Eloquent模型的查询及差异](#Laravel DB门面和Eloquent模型的查询及差异 "#laravel-db%E9%97%A8%E9%9D%A2%E5%92%8Celoquent%E6%A8%A1%E5%9E%8B%E7%9A%84%E6%9F%A5%E8%AF%A2%E5%8F%8A%E5%B7%AE%E5%BC%82")
- 目录
- [一. DB门面(查询构建器)](#一. DB门面(查询构建器) "#%E4%B8%80-db%E9%97%A8%E9%9D%A2%E6%9F%A5%E8%AF%A2%E6%9E%84%E5%BB%BA%E5%99%A8")
- 1.查询实例
- [2. 常用查询方法](#2. 常用查询方法 "#2-%E5%B8%B8%E7%94%A8%E6%9F%A5%E8%AF%A2%E6%96%B9%E6%B3%95")
- [二. Eloquent ORM(模型查询)](#二. Eloquent ORM(模型查询) "#%E4%BA%8C-eloquent-orm%E6%A8%A1%E5%9E%8B%E6%9F%A5%E8%AF%A2")
- [1. 查询实例](#1. 查询实例 "#1-%E6%9F%A5%E8%AF%A2%E5%AE%9E%E4%BE%8B")
- [2. 常用查询方法](#2. 常用查询方法 "#2-%E5%B8%B8%E7%94%A8%E6%9F%A5%E8%AF%A2%E6%96%B9%E6%B3%95-1")
- [三. 两者的区别和避坑点](#三. 两者的区别和避坑点 "#%E4%B8%89-%E4%B8%A4%E8%80%85%E7%9A%84%E5%8C%BA%E5%88%AB%E5%92%8C%E9%81%BF%E5%9D%91%E7%82%B9")
- [1. DB门面和与模型查询实例的关联和区别](#1. DB门面和与模型查询实例的关联和区别 "#1-db%E9%97%A8%E9%9D%A2%E5%92%8C%E4%B8%8E%E6%A8%A1%E5%9E%8B%E6%9F%A5%E8%AF%A2%E5%AE%9E%E4%BE%8B%E7%9A%84%E5%85%B3%E8%81%94%E5%92%8C%E5%8C%BA%E5%88%AB")
- [2. 典型报错场景与解决方案](#2. 典型报错场景与解决方案 "#2-%E5%85%B8%E5%9E%8B%E6%8A%A5%E9%94%99%E5%9C%BA%E6%99%AF%E4%B8%8E%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88")
- [问题: 模型类取实例属性时例如已设置的分组字段groups 会出现报错
Exception: Property [groups] does not exist on the Eloquent builder instance
](#问题: 模型类取实例属性时例如已设置的分组字段groups 会出现报错 Exception: Property [groups] does not exist on the Eloquent builder instance "#%E9%97%AE%E9%A2%98-%E6%A8%A1%E5%9E%8B%E7%B1%BB%E5%8F%96%E5%AE%9E%E4%BE%8B%E5%B1%9E%E6%80%A7%E6%97%B6%E4%BE%8B%E5%A6%82%E5%B7%B2%E8%AE%BE%E7%BD%AE%E7%9A%84%E5%88%86%E7%BB%84%E5%AD%97%E6%AE%B5groups-%E4%BC%9A%E5%87%BA%E7%8E%B0%E6%8A%A5%E9%94%99-exception-property-groups-does-not-exist-on-the-eloquent-builder-instance-")
- [问题: 模型类取实例属性时例如已设置的分组字段groups 会出现报错
一. DB门面(查询构建器)
1.查询实例
查询实例对象解析:
返回的实例对象为Illuminate\Database\Query\Builder
php
$result = DB::table("表名");
// 打印$result结果
Illuminate\Database\Query\Builder {
...
}
切换多数据库:
可使用connection()
方法选择指定的数据库,返回实例也为 Illuminate\Database\Query\Builder
,因为此调用first()
或get()
等方法得到的结果与直接使用DB::table("表名")调用一样;
php
$result = DB::connection('数据库连接别名')->table("表名");
// 打印$result结果
Illuminate\Database\Query\Builder {
}
2. 常用查询方法
get()方法详解
-
返回数据类型:
结果集是一个
Illuminate\Support\Collection
对象实例, 其中每个子项都是实际上是PHP StdClass
对象的一个实例php// 查询方法 $data = DB::table('user')->whereIn('id', [1,2])->get(); // 取值结果 foreach($data as $da) { $userId = $da->id; // 子项都是对象,只能采用对象取值 }
有值返回的打印结果
bashIlluminate\Support\Collection^ {#2184 #items: array:2 [ 0 => {#2195 +"id": 1 } 1 => {#2186 +"id": 2 } ] }
无值返回的结果
bashIlluminate\Support\Collection^ {#2184 #items: [] }
-
空结果判断:
可以通过
isEmpty()
方法判断是否存在数据对象, 存在为false, 不存在为true -
结果集转化为二维数组:
❌ 错误方式: 使用
get()->toArray()
, 会得到一个数组,但数组子元素还是StdClass对象的实例, 查询无结果时为空数组;bash# 返回值 array:2 [ 0 => {#2195 +"id": 1 } 1 => {#2186 +"id": 2 } ]
php$data = DB::table('user')->select(['id'])->get()->toArray(); // 因此只能用对象取值法 foreach ($data as $da) { $userId = $da->id; }
✅ 正确方式: 可采用
map()
方法,将数据子项对象强制转化为数组。php$data = DB::table('user')->select(['id'])->get()->map(function($item) { return (array)$item; })->toArray(); // 数组可直接使用empty()判断是否有数据 if (empty($data)) { return "暂无数据"; } foreach ($data as $da) { $userId = $da['id']; // 采用数组方式取值,无法通过对象取值了 }
first()方法详解
-
返回数据类型:
查询有结果时,返回一个StdClass对象实例;查询无结果时返回null;
php$info = DB::table('user')->where('id', 1)->first();
bash# 返回值结果 {#2197 +"id": 1 +"name": "demo" }
-
空结果判断:
可以通过
empty()
方法判断是否存在数据对象, 存在为false, 不存在为true -
转化为二维数组: 可以通过
->toArray()
转化,先判断是否为空再进行转化,否则会报错php$data = User::where('id', 1)->first()->toArray(); $data = $data ? $data->toArray() : [];
-
变形语法:
简写化写法
find()
,find(1)
等价于->where('id',1)->first()
二. Eloquent ORM(模型查询)
1. 查询实例
查询实例对象解析:
返回的实例对象为Illuminate\Database\Eloquent\Builder
php
$result = User::query();
// 打印result结果
Illuminate\Database\Eloquent\Builder^ {#2188
...
}
两种语法:
php
// 常用写法
$result = User::where('id', 1);
// 等价于上面的语法,返回实例相同,是上面语法的完整版
$result = User::query()->where('id', 1);
切换多数据库:
通过模型类中$connection
属性来控制数据库切换
2. 常用查询方法
get()方法详解
-
返回数据类型:
结果集是一个
Illuminate\Database\Eloquent\Collection
对象,其子项是模型对象实例,例如 App\Model\Userphp// 查询方法 $data = User::whereIn('id', [1, 2])->get(); // 取值结果 (数组或对象取值都可以) foreach ($data as $da) { $userId = $da->id; $userName = $da['name']; }
有值返回的打印结果
bashIlluminate\Database\Eloquent\Collection^ {#2203 #items: array:2 [ 0 => App\Model\User^ {#2204 #table: "user" #guarded: [] +timestamps: false #connection: "mysql" #primaryKey: "id" #keyType: "int" +incrementing: true #with: [] #withCount: [] #perPage: 15 +exists: true +wasRecentlyCreated: false #attributes: array:24 [ "id" => 1 "name" => "测试" ] #original: array:24 [ "id" => 1 "name" => "测试" ] #changes: [] #casts: [] #dates: [] #dateFormat: null #appends: [] #dispatchesEvents: [] #observables: [] #relations: [] #touches: [] #hidden: [] #visible: [] #fillable: [] } ] }
-
空结果判断 可以通过
isEmpty()
方法判断是否存在数据对象, 存在为false, 不存在为true -
结果转化为二维数组 使用
get()->toArray()
,有值返回的标准的二维数组,无值返回空数组
first()方法详解
-
返回数据类型:
查询有结果时,返回一个模型对象实例; 查询无结果时返回null; -
空结果判断 可以通过
empty()
方法判断是否存在数据对象, 存在为false, 不存在为true -
转化为二维数组: 可以通过
->toArray()
转化,先判断是否为空再进行转化,否则会报错php$data = User::where('id', 1)->first()->toArray(); $data = $data ? $data->toArray() : [];
三. 两者的区别和避坑点
1. DB门面和与模型查询实例的关联和区别
对比关系
维度 | DB门面 | 模型Eloquent |
---|---|---|
返回实例 | Illuminate\Database\Query\Builder | Illuminate\Database\Eloquent\Builder |
内存占用 | 较低(StdClass对象) | 较高(模型对象) |
查询复杂度 | 适合简单查询 | 支持复杂模型关联 |
2. 典型报错场景与解决方案
问题: 模型类取实例属性时例如已设置的分组字段groups 会出现报错 Exception: Property [groups] does not exist on the Eloquent builder instance
- 原因: 模型类是基于查询构造器实例的基础上封装,它无法直接获取查询构造器中的属性
- 解决方法: 通过调用
getQuery()
,获取基础的查询构造器实例,然后再获取属性。从而获取关键属性信息如分组字段groups
、查询字段columns
、排序字段orders
php
$builder = User::query();
// 会报错
$builder->groups;
// 正确做法, 此时会调用查询构造器实例
$builder->getQuery()->groups;