查询生成器的行为就像雄辩

Posted

技术标签:

【中文标题】查询生成器的行为就像雄辩【英文标题】:Query Builder acts like eloquent 【发布时间】:2021-11-08 03:08:13 【问题描述】:

我只是想知道,我可以在 Laravel 上使用查询构建器创建“雄辩的关系”吗?有没有办法做到这一点?

示例:

我有两张桌子

users
========
user_id
user_name

events
========
event_id
event_name
user_id

我知道如果我想选择事件并想向创建事件的用户展示我可以这样做

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class User extends Model

    public function events() 
        return $this->belongsTo(Event::class, 'user_id', 'user_id');
    

在Controller中我可以这样称呼它

User::find(1)->with('events');

但在这种情况下,我有一个复杂的查询并加入 3 个表,我担心复杂性,所以我只想使用查询生成器而不是 eloquent,但是有没有办法让它像 eloquent 的行为一样?

期望:(我知道这是一个错误的查询,但有办法做到吗?)

DB::select('select * from users where user_id = ?', [1])->with('events');

预期结果示例:

user: 
    user_id: 1,
    user_name: 'Mr. Man',
    events: [
        
            event_id: 1,
            event_name: 'Birthday Party'
        ,
        
            event_id: 2,
            event_name: 'Honey Moon'
        
    ]

编辑:

我想我也必须像我的情况一样说清楚,这是我所期望的

我有三张桌子

users
=====
user_id

events
======
event_id
user_id
event_location
event_date

event_organizers
================
event_organizer_id
event_organizer_name

package_event_organizers
========================
package_event_organizer_id
event_organizer_id
package_event_organizer_name

我的期望

events: [
    
        event_organizer_id: 1,
        event_organizer_name: 'Wedding',
        event_location: 'New York',
        event_date: '2021/09/12',
        package_event_organizers: [
            
                package_event_organizer_id: 1,
                package_event_organizer_id: 'Wedding Package 1',
            ,
            
                package_event_organizer_id: 2,
                package_event_organizer_id: 'Wedding Package 2',
            
        ]
    ,
    
        event_organizer_id: 1,
        event_organizer_name: 'Wedding',
        event_location: 'San Fransisco',
        event_date: '2021/10/12',
        package_event_organizers: [
            
                package_event_organizer_id: 1,
                package_event_organizer_id: 'Wedding Package 1',
            ,
            
                package_event_organizer_id: 2,
                package_event_organizer_id: 'Wedding Package 2',
            
        ]
    ,
    
        event_organizer_id: 2,
        event_organizer_name: 'Sweet 17',
        event_location: 'Chicago',
        event_date: '2021/11/12',
        package_event_organizers: [
            
                package_event_organizer_id: 1,
                package_event_organizer_id: 'Sweet 17 Package 1',
            ,
            
                package_event_organizer_id: 2,
                package_event_organizer_id: 'Sweet 17 Package 2',
            
        ]
    
]

【问题讨论】:

不,你不能这样做。另外,您为什么要这样做?这里的用例不清楚。 您好,感谢您的关注。我想这样做是因为我想返回一个我需要加入 3 个表的数据集合,之后每个对象也会有数据集合 是的,我不明白为什么不用 eloquent 而不是 joins 目前,我仍然使用 eloquent,但我只是想知道我能否让查询生成器表现得像 eloquent。我从一些资源中读到它说使用 eloquent 的关系太多会增加复杂性 这句话过于宽泛,实际上没有意义。 3 次连接通常比在 3 种不同的关系上执行 with 慢,因为您从连接中获得所有冗余数据,所以它是否更慢取决于用例。 【参考方案1】:

我不认为这是可能的,你建立的关系是属于它自己的模型的函数。当你使用 DB 时,将返回一个 laravel 集合的实例,并且这个集合没有称为事件的函数

【讨论】:

【参考方案2】:

使用 eloquent 时,每条获取的记录都会实例化一个模型,因此您可以对关系使用预加载。

当您使用 Query Builder 编写查询时,您实际上是在编写未实例化模型的原始查询。

使用查询构建器检索关系的唯一方法是使用本机数据库连接手动执行此操作,或循环遍历每条记录并使用获取的模型构建一个集合。

$raw_users = DB::select('select * from users where user_id = ?', [1]);

$users = collect();
foreach ($raw_users as $user) 
    $users->add(User::find($user->user_id)->with('events'));


return $users;

如果您没有遇到任何性能问题,我建议您使用 eloquent,因为它很简单,否则,只需编写您自己的原始查询。

做我上面写的工作,但只是浪费资源。

【讨论】:

感谢您的洞察力,您认为我喜欢您的更好还是使用 eloquent 代替(有 3 个表可以加入并返回一个表的集合) 这取决于您的查询性能。根据我的经验,如果您只进行 3 个简单的连接,并且正在处理记录很少的表,那么请继续使用 eloquent 并避免头痛。如果您需要连接一些具有数百万条记录的表,如果您的索引没有很好地声明,您可能会遇到性能问题和内存峰值。在这种情况下,编写一个原始查询。

以上是关于查询生成器的行为就像雄辩的主要内容,如果未能解决你的问题,请参考以下文章

我雄辩的查询构建器实例返回空,而 sql 子句返回结果。会欣赏第二只眼睛

雄辩给出错误,但查询在 phpmyadmin 中执行良好

laravel 4 - 如何限制(采取和跳过)雄辩的 ORM?

Laravel 使用按 id 搜索的查询生成器有线行为

改变 WIX 生成的 .NET 3.5 引导程序的行为

groupBy 在 laravel 中具有雄辩的关系