【问题标题】:How to fetch two related objects in Laravel (Eloquent) with one SQL query如何使用一个 SQL 查询在 Laravel (Eloquent) 中获取两个相关对象
【发布时间】:2017-03-08 06:42:46
【问题描述】:

我正在尝试根据文档使用预先加载在 Laravel 中获取两个相关对象。

https://laravel.com/docs/5.4/eloquent-relationships#eager-loading

我的模型是:

class Lead extends Model {
  public function session() {
    return $this->hasOne('App\LeadSession');
  }
}

class LeadSession extends Model {
  public function lead() {
    return $this->belongsTo('App\Lead');
  }
}

我想用一个 SQL 查询来获取这两个对象。基本上我想执行:

select * from lead_sessions as s 
inner join lead as l 
on l.id = s.lead_id 
where s.token = '$token';

然后能够访问 LeadSession 和 Lead 对象。这是我正在尝试的 php 代码:

$lead = Lead::with(['session' => function ($q) use ($token) {
  $q->where('token','=',$token);
}])->firstOrFail();

print($lead->session->id);

我也试过了:

$lead = Lead::whereHas('session', function($q) use ($token) {
  $q->where('token','=',$token);
})->firstOrFail();

print($lead->session->id);

$session = LeadSession::with('lead')->where('token',$token)->firstOrFail();

print($session->lead->id);

在这三种情况下,我执行了两个查询,一个针对leads 表,另一个针对lead_sessions 表。

在 Eloquent 中这样的事情是可能的吗?在我看来,它应该是一个标准的 ORM 操作,但由于某种原因,我为此苦苦挣扎了一整天。

我不想使用查询生成器,因为我想在之后使用 Eloquent 对象及其函数。

我来自 Python 和 Django,我想在 Django 中复制 select_related 函数的行为。

【问题讨论】:

  • 只是为了确保我理解您的问题,您希望 Eloquent 只生成 1 个查询还是 2 个?
  • @RossWilson,是的。两个模型都可以使用连接查询来检索

标签: laravel eloquent


【解决方案1】:

试试这个,看看它是否会产生多个查询

$session = LeadSession::join('leads', 'leads.id', '=', 'lead_sessions.lead_id')
->where('token',$token)
->firstOrFail();

我希望它只运行一个查询。我没有测试这个。不确定是否必须添加 select() 才能选择列。但是,是的,先试试这个。

更新 只需添加如何使用会话和潜在客户数据。尝试选择并指定您需要的数据。原因是如果两个表都有类似的列,如“id”,其中一个将被覆盖。所以你必须给你的选择起别名

$session = LeadSession::join('leads', 'leads.id', '=', 'lead_sessions.lead_id')
->where('token',$token)
->select(
    'lead_sessions.*',
    'leads.id as lead_id',
    'leads.name',
    'leads.more_stuff'
)
->firstOrFail();

现在所有这些数据都属于$session 变量。为了测试你正在做的事情

print($lead->session->id);
//becomes 
print($session->lead_id); //we aliased this in the query

【讨论】:

  • $session->lead->id 是通过急切加载进行查询的人。在此处阅读:laravel.com/docs/5.4/eloquent-relationships#eager-loading 第一次编写该查询时会进行查询。我的建议是让您一次性获取所有数据,然后使用而无需急切加载。
  • 我删除了急切加载代码,还是一样。它首先使用连接执行一个查询:select * from lead_sessions inner join leads on leads.id = lead_sessions.lead_id where token = ?,然后继续执行另一个查询:select * from leads where leads.id = ?
  • 是的,我已经编辑了我之前的评论,并添加了在打印上执行的两个查询。打印后我有一个 die(),所以它停止了。
  • 我不得不承认你有一个非常复杂的用例。这是一个很好的挑战,但我不得不承认,我无法在使用 Eloquent 的一个查询中找到一种方法。
  • 不是一个非常复杂的用例。我只想优化应用程序中的数据库操作。实际操作更复杂,它连接了四个相关模型,所以我想在一个查询中获取它们,而不是执行四个。对于 ORM 来说,这应该是相当常见的操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-17
  • 2011-12-23
  • 2021-04-19
  • 2017-10-24
  • 2018-09-24
  • 2016-09-05
相关资源
最近更新 更多