使用 eloquent 从多个连接中检索数据
Posted
技术标签:
【中文标题】使用 eloquent 从多个连接中检索数据【英文标题】:Retrieve data from multiple joins using eloquent 【发布时间】:2020-04-30 10:55:55 【问题描述】:我正在开发一个项目来跟踪货物的交付。 我的想法是一次送货可以去不同的地方,所有这些地方都通过单程连接。
这是我的 Eloquent 架构:
class Delivery extends Model
public function places()
return $this->hasMany(Place::CLASS, 'delivery_id');
public function trips()
// what should I do here?
class Place extends Model
public function delivery()
return $this->belongsTo(Delivery::CLASS, 'delivery_id');
class Trip extends Model
public function departurePlace()
return $this->belongsTo(Place::CLASS, 'departure_place_id');
public function arrivalPlace()
return $this->belongsTo(Place::CLASS, 'arrival_place_id');
基本上,我要做的是获取与一次交付相关的所有行程。或者,换一种说法,连接一次送货必须经过的所有地方的所有行程。 这是实现我想要的结果的 SQL 查询:
select distinct trip.*
from delivery
join place on (place.delivery_id = delivery.id)
join trip on (place.id = trip.arrival_place_id or place.id = trip.departure_place_id)
我想在我的 Delivery
模型上有一个 trips()
方法,它返回该结果。
但是,我对如何使用 Eloquent 实现这一点感到非常困惑。
【问题讨论】:
从我上面看到的查询来看,送货和旅行之间似乎没有直接联系。如果我正确理解了查询,那将返回曾经在交货地点进行的所有旅行。 是的,完全正确。送货和旅行之间没有联系。需要首先通过场所连接,如 SQL 查询所示。抱歉,我刚刚注意到我的问题中有一个错误。 您的意思是获取所有通过地点的送货行程吗? @Saengdaet 是的,我就是这个意思。 【参考方案1】:不幸的是,我们本可以简单地使用union
方法来实现这一点,但它似乎不适用于hasManyThrough
relations。
无论如何,我认为Eloquent
关系并不意味着用于实现这样的特定查询。
相反,您可以使用Eloquent
scopes 来实现此目的。
所以根据@Saengdaet 的回答,我们可以写两个关系,然后将它们与scope
结合起来:
(顺便说一句:我不知道你为什么说他的代码出错了......)
class Delivery extends Model
public function places()
return $this->hasMany(Place::class);
public function outboundTrips()
return $this->hasManyThrough(
Trip::class,
Place::class,
"delivery_id", // Foreign key on places table
"departure_place_id", // Foreign key on trips table
);
public function inboundTrips()
return $this->hasManyThrough(
Trip::class,
Place::class,
"delivery_id", // Foreign key on places table
"arrival_place_id", // Foreign key on trips table
);
public function scopeTrips($query)
$deliveriesWithTrips = $query->with(['outboundTrips', 'inboundTrips'])->get();
$trips = [];
$deliveriesWithTrips->each(function ($elt) use (&$trips)
$trips[] = $elt->inboundTrips->merge($elt->outboundTrips);
);
return $trips;
现在要检索给定交货的所有行程,您只需编写:
Delivery::where('id', $id)->trips();
【讨论】:
【参考方案2】:如果您想使用Delivery
模型获取所有行程,您可以使用“hasManyThrough”关系,它提供了通过中间关系访问远距离关系的便捷快捷方式。
但您必须选择您将使用 Trip
模型上的哪个 FK 来关联它
可以参考"has-many-through" relationship
class Delivery extends Model
public function places()
return $this->hasMany(Place::CLASS, 'delivery_id');
public function trips()
return $this->hasManyThrough(
Trip::Class,
Place::Class,
"delivery_id", // Foreign key on places table
"departure_place_id", // Foreign key on trips table
"id", // Local key on deliveries table
"id" // Local key on places table
);
【讨论】:
您的代码给了我一个错误。我将其更改为return $this->hasManyThrough(Trip::Class, Place::Class, 'travel_id', 'departure_place_id');
> 它可以工作,但显然这并没有返回我想要的所有结果,因为它缺少 arrival_place_id
的额外条件。虽然hasManyThrough
看起来是一个有趣的功能(我不知道),但也许它不是实现我想要的结果的正确方法?
啊我明白了,我只是给你举个例子,因为我实际上并不知道你的 FK 和你的 PK 是什么。
也许你可以在 hasManyThrough 之后添加更多 where 条件来过滤它们以上是关于使用 eloquent 从多个连接中检索数据的主要内容,如果未能解决你的问题,请参考以下文章
Vue 2 Laravel 5.3 Eloquent 无法从对象中检索数据
从 table1 中检索数据,但在 table2 中进行比较 - Laravel eloquent