php 有一个通过 Laravel Eloquent
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27466542/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Has one through Laravel Eloquent
提问by yayuj
I have three tables garages
, cars
, securities
.
我有三个表garages
,cars
,securities
。
The securities are the ones that is keeping one car safe, you can have more than one security, but a single security can keep only one car safe. The garage is where the car is and the securities are as well.
证券是保证一辆车安全的证券,您可以拥有多个证券,但一个证券只能保证一辆车的安全。车库是汽车所在的地方,证券也是。
What I want is to list all the securities and know the name of the garage that he is. The problem is that securities
doesn't have a column containing the id of the garage, only the id of the car that he is keeping safe, but car has the id of the garage.
我想要的是列出所有证券并知道他所在的车库的名称。问题是securities
没有包含车库 id 的列,只有他保持安全的汽车的 id,但是 car 有车库的 id。
Laravel Eloquent has a method called hasManyThrough
, but securities
has one garage
through cars
only.
Laravel雄辩有一个名为方法hasManyThrough
,但securities
有一个garage
通过cars
唯一的。
Here is the tables:
以下是表格:
garages table:
车库表:
-----------------------------------
|garage_id|garage_name|garage_size|
-----------------------------------
| 1| Garage 1| 200|
-----------------------------------
| 2| Garage 2| 400|
-----------------------------------
cars table:
汽车表:
---------------------------
|car_id|car_name|garage_id|
---------------------------
| 1| Car 1| 1|
---------------------------
| 2| Car 2| 1|
---------------------------
| 3| Car 3| 2|
---------------------------
securities table:
证券表:
----------------------------------
|security_id|security_name|car_id|
----------------------------------
| 1| Security 1| 1|
----------------------------------
| 2| Security 2| 1|
----------------------------------
| 3| Security 3| 2|
----------------------------------
| 4| Security 4| 3|
----------------------------------
The output must to be:
输出必须是:
Security 1 is on Garage 1
Security 2 is on Garage 1
Security 3 is on Garage 1
Security 4 is on Garage 2
And I have the models:
我有模型:
The code is to list the garages, but I want to make similar but to list the securities (just for you to have an idea of how the structure is).
代码是列出车库,但我想做类似但列出证券(只是为了让您了解结构如何)。
$garages = Garages::with(['cars', 'securities'])->get();
$garages->transform(function($garages) {
return array(
'garage_name' => $garage->garage_name,
'count_cars' => $garage->cars->count(),
'count_securities' => $garage->securities->count(),
);
});
class Garages extends Eloquent
{
public function cars()
{
return $this->hasMany('cars');
}
public function securities()
{
return $this->hasMany('securities');
}
}
class Cars extends Eloquent
{
}
class Securities extends Eloquent
{
}
And just to make an emphasis again: I want to have the name of the garage related to the car that the security is keeping safe.
再次强调:我想要与安全部门保持安全的汽车相关的车库名称。
Just to make it even easier to understand, if I do this:
只是为了让它更容易理解,如果我这样做:
$securities = Securities::with(['cars'])->get();
class Securities extends Eloquent
{
public function cars()
{
return $this->hasOne('cars');
}
}
I will get only the garage_id
from cars
table as relations. What I really want is the name of the garage.
我会得到只有garage_id
从cars
表作为关系。我真正想要的是车库的名字。
[relations:protected] => Array
(
[cars] => Cars Object
(
...
[attributes:protected] => Array
(
...
[car_name] => Car 1
[garage_id] => 1
...
回答by Gufran
It looks like you are not relating objects correctly. Let's break that down:
看起来您没有正确关联对象。让我们分解一下:
If a Garage
Has Many Car
then a Car
Belongs To Garage
, Lets proceed with this idea in mind.
如果 a Garage
Has Many Car
then a Car
Belongs To Garage
,让我们记住这个想法。
Garage
Has ManyCar
Car
Has ManySecurity
Security
Belongs ToCar
Garage
Has ManySecurity
ThroughCar
Garage
有很多Car
Car
有很多Security
Security
属于Car
Garage
有很多Security
通过Car
In Eloquent you can just go ahead and clap those relations in, it should work given the schema you posted above.
在 Eloquent 中,您可以继续并为这些关系鼓掌,鉴于您在上面发布的架构,它应该可以工作。
class Garage extends Eloquent
{
public function cars()
{
return $this->hasMany('cars');
}
public function securities()
{
return $this->hasManyThrough('Security', 'Car');
}
}
class Car extends Eloquent
{
public function securities()
{
return $this->hasMany('Security');
}
// ADDED IN SECOND EDIT
public function garage()
{
return $this->belongsTo('Garage');
}
}
class Security extends Eloquent
{
public function car()
{
return $this->belongsTo('Car');
}
}
And that should be it.
应该就是这样。
EDIT:You can access all these relations from any model as long as there is a path you can draw from one model to another using a combination of these relations. Check this out for example:
编辑:您可以从任何模型访问所有这些关系,只要有一条路径可以使用这些关系的组合从一个模型绘制到另一个模型。看看这个,例如:
$security = Security::with('car.garage')->first();
will retrieve first Security
record and load Car
relation on it, then it goes one more step and load all Garage
relations on every Car
object loaded under Security
model.
将检索第一条Security
记录并Car
在其上加载关系,然后再执行一步并加载模型下加载的Garage
每个Car
对象上的所有关系Security
。
You can access them using this syntax:
您可以使用以下语法访问它们:
$security->car->garage->id
// Other examples
$garage = Garage::with('cars.securities')->first();
foreach($garage->cars as $car)
{
foreach($cars->securities as $security)
{
echo "Car {$car->id} has {$security->id} assigned to it";
}
}
Furthermore, notice that the relationship objects are an instance of Collection
so you have all the fancy methods such as ->each()
, ->count()
, ->map()
available on them.
此外,请注意关系对象是 的一个实例,Collection
因此您可以在它们上使用所有花哨的方法,例如->each()
, ->count()
, ->map()
。
回答by Eric Tucker
I ran into a similar problem recently and was able to do something like this:
我最近遇到了类似的问题,并且能够做这样的事情:
class Cars extends Eloquent
{
public function garage()
{
return $this->hasOne('Garages');
}
}
class Securities extends Eloquent
{
public function car()
{
return $this->hasOne('Cars');
}
public function garage()
{
return $this->car->garage();
}
}
This gives you the Securities has one garage relationship and you can do something like:
这使您的证券有一个车库关系,您可以执行以下操作:
$securities = Securities::with('garage')->get();
foreach($securities as $security)
{
echo $security->security_name . ' is on ' . $security->garage->garage_name;
}
回答by danrichards
This is relevant to your original inquiry.
这与您的原始查询有关。
hasOneThrough will be available in Laravel 5.8
hasOneThrough 将在 Laravel 5.8 中可用
回答by pablorsk
You can use hasOneThrough
, integrated on Laravel => 5.8.
您可以使用hasOneThrough
, 集成在 Laravel => 5.8 上。
public function garage()
{
return $this->hasOneThrough(
Garage::class,
Car::class,
'car_id',
'id',
null,
'garage_id'
);
}
Dont use solutions like
不要使用类似的解决方案
return $this->car->garage();
Because it are using eager loading, and you call to database on each iteration. These type of solution are not optimized.
因为它使用的是预先加载,并且您在每次迭代时都会调用数据库。这些类型的解决方案没有优化。