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;
相关推荐
kkk162224518 小时前
Laravel框架下通过DB获取数据并转为数组的方法
数据库·oracle·laravel
HOOLOO5 天前
Docker部署Laravel项目
docker·laravel·php-fpm
道系女孩~8 天前
laravel项目中使用FFMPeg 剪裁视频
php·laravel
斯密码赛我是美女10 天前
laravel Blade 模板引擎
php·laravel
菜鸟码农_Shi14 天前
Laravel 队列入门全攻略:从基础到实战
laravel
rorg16 天前
搭建laravle 数字产品销售平台 php
php·laravel
Мартин.1 个月前
[Meachines] [Easy] Horizontall Strapi RCE+KTOR-HTTP扫描+Laravel Monolog 权限提升
网络协议·http·laravel·ctf
轨迹coding1 个月前
Ubuntu+Laravel+MQ+Supervisor队列系统搭建流程
linux·ubuntu·rabbitmq·laravel
清风细雨_林木木2 个月前
wangEditor富文本编辑器,Laravel上传图片配置和使用
php·laravel