Laravel DB门面和Eloquent模型的查询及差异

目录

  • [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")
    • [二. Eloquent ORM(模型查询)](#二. Eloquent ORM(模型查询) "#%E4%BA%8C-eloquent-orm%E6%A8%A1%E5%9E%8B%E6%9F%A5%E8%AF%A2")
    • [三. 两者的区别和避坑点](#三. 两者的区别和避坑点 "#%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-")

一. 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; //  子项都是对象,只能采用对象取值
    }

    有值返回的打印结果

    bash 复制代码
    Illuminate\Support\Collection^ {#2184
       #items: array:2 [
          0 => {#2195
             +"id": 1
          }
          1 => {#2186
             +"id": 2
          }
       ]
    }

    无值返回的结果

    bash 复制代码
    Illuminate\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\User

    php 复制代码
    // 查询方法
    $data = User::whereIn('id', [1, 2])->get();
    
    // 取值结果 (数组或对象取值都可以)
    foreach ($data as $da) {
       $userId = $da->id;
       $userName = $da['name'];
    }

    有值返回的打印结果

    bash 复制代码
    Illuminate\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;
相关推荐
深山技术宅2 天前
在 Laravel 12 中实现 WebSocket 通信
websocket·php·laravel
深山技术宅2 天前
laravel 12 监听syslog消息,并将消息格式化后存入mongodb
mongodb·php·laravel
深山技术宅5 天前
Laravel 12 实现 API 登录令牌认证
php·laravel
深山技术宅6 天前
Laravel 12 实现 OAuth2 登录
php·laravel
Taichi呀6 天前
Laravel+API 接口
php·laravel
Taichi呀8 天前
Laravel基础
php·laravel
foryoufeng12 天前
Laravel代码生成器,快速构建项目代码,统一团队编码风格
php·laravel
奔跑的皮皮虾16 天前
Laravel 对接阿里云 OSS 说明文档
阿里云·php·laravel
奔跑吧邓邓子22 天前
宝塔面板中解锁Laravel日志查看的奥秘
laravel·宝塔面板·日志查看
86Eric23 天前
Laravel 实现 队列 发送邮件功能
php·laravel·队列·异步执行