![](/img/trans.png)
[英]Laravel hasManyThrough equivalent: belongsTo relationship through another model
[英]How to set Eloquent relationship belongsTo THROUGH another model in Laravel?
我有一個模型列表,它通過它的belongsTo('Model') 關系繼承應該本質上屬於其對應模型所屬的制造商。
這是來自我的列表模型:
public function model()
{
return $this->belongsTo('Model', 'model_id');
}
public function manufacturer()
{
return $this->belongsTo('Manufacturer', 'models.manufacturer_id');
/*
$manufacturer_id = $this->model->manufacturer_id;
return Manufacturer::find($manufacturer_id)->name;*/
}
和我的制造商模型:
public function listings()
{
return $this->hasManyThrough('Listing', 'Model', 'manufacturer_id', 'model_id');
}
public function models()
{
return $this->hasMany('Model', 'manufacturer_id');
}
我可以在視圖中回顯 $listing->model->name,但不能回顯 $listing->manufacturer->name。 這會引發錯誤。 我嘗試在 Listing 模型中注釋掉 2 行只是為了獲得效果,然后我可以 echo $listing->manufacturer() 並且這會起作用,但這並不能正確建立它們的關系。 我該怎么做呢? 謝謝。
修訂上市模型(感謝回答者):
public function model()
{
return $this->belongsTo('Model', 'model_id');
}
public function manufacturer()
{
return $this->belongsTo('Model', 'model_id')
->join('manufacturers', 'manufacturers.id', '=', 'models.manufacturer_id');
}
我找到了一個解決方案,但它不是非常簡單。 我已經在下面發布了它,但我首先發布了我認為更好的解決方案。
您不應該能夠直接從列表中訪問制造商,因為制造商僅適用於模型。 盡管您可以從列表對象中預先加載制造商關系,但請參見下文。
class Listing extends Eloquent
{
public function model()
{
return $this->belongsTo('Model', 'model_id');
}
}
class Model extends Eloquent
{
public function manufacturer()
{
return $this->belongsTo('manufacturer');
}
}
class Manufacturer extends Eloquent
{
}
$listings = Listing::with('model.manufacturer')->all();
foreach($listings as $listing) {
echo $listing->model->name . ' by ' . $listing->model->manufacturer->name;
}
為了使您要求的解決方案起作用,需要花費一些時間。 解決方案如下所示:
public function manufacturer()
{
$instance = new Manufacturer();
$instance->setTable('models');
$query = $instance->newQuery();
return (new BelongsTo($query, $this, 'model_id', $instance->getKeyName(), 'manufacturer'))
->join('manufacturers', 'manufacturers.id', '=', 'models.manufacturer_id')
->select(DB::raw('manufacturers.*'));
}
我首先處理查詢並從中構建響應。 我想要創建的查詢是這樣的:
SELECT * FROM manufacturers ma
JOIN models m on m.manufacturer_id = ma.id
WHERE m.id in (?)
通常通過執行return $this->belongsTo('Manufacturer');
創建的查詢return $this->belongsTo('Manufacturer');
select * from `manufacturers` where `manufacturers`.`id` in (?)
?
將被列表表中的manufacturer_id
ID 列的值替換。 此列不存在,因此將插入單個 0,並且您永遠不會返回制造商。
在我想重新創建的查詢中,我受到了models.id
約束。 通過定義外鍵,我可以在我的關系中輕松訪問該值。 於是關系變成了
return $this->belongsTo('Manufacturer', 'model_id');
這會產生與之前相同的查詢,但會填充?
與model_ids。 所以這會返回結果,但通常是不正確的結果。 然后我打算更改我從中選擇的基表。 這個值來自模型,所以我將傳入的模型更改為Model
。
return $this->belongsTo('Model', 'model_id');
我們現在已經模仿了模型關系,所以很好,我還沒有真正到任何地方。 但至少現在,我可以連接到制造商表。 所以我再次更新了關系:
return $this->belongsTo('Model', 'model_id')
->join('manufacturers', 'manufacturers.id', '=', 'models.manufacturer_id');
這讓我們更近了一步,生成了以下查詢:
select * from `models`
inner join `manufacturers` on `manufacturers`.`id` = `models`.`manufacturer_id`
where `models`.`id` in (?)
從這里開始,我想將我查詢的列限制為制造商列,為此我添加了選擇規范。 這使關系變為:
返回 $this->belongsTo('Model', 'model_id') ->join('manufacturers', 'manufacturers.id', '=', 'models.manufacturer_id') ->select(DB::raw('manufacturers) .*'));
並得到了查詢
select manufacturers.* from `models`
inner join `manufacturers` on `manufacturers`.`id` = `models`.`manufacturer_id`
where `models`.`id` in (?)
現在我們有一個 100% 有效的查詢,但是從關系中返回的對象是Model
而不是Manufacturer
類型。 這就是最后一點詭計出現的地方。我需要返回一個Manufacturer, but wanted it to constrain by the
table in the where clause. I created a new instance of Manufacturer and set the table to
Manufacturer, but wanted it to constrain by the
模型table in the where clause. I created a new instance of Manufacturer and set the table to
Manufacturer, but wanted it to constrain by the
table in the where clause. I created a new instance of Manufacturer and set the table to
table in the where clause. I created a new instance of Manufacturer and set the table to
模型並手動創建關系。
重要的是要注意,保存是行不通的。
$listing = Listing::find(1);
$listing->manufacturer()->associate(Manufacturer::create([]));
$listing->save();
這將創建一個新的制造商,然后將listings.model_id
更新為新制造商的 ID。
我想這可能會有所幫助,它幫助了我:
class Car extends Model
{
public function mechanical()
{
return $this->belongsTo(Mechanical::class);
}
}
class CarPiece extends Model
{
public function car()
{
return $this->belongsTo(Car::class);
}
public function mechanical()
{
return $this->car->mechanical();
}
}
至少,正是這種需求讓我想到了belongsToThrough的存在
您可以執行以下操作(學生組 -> 用戶 -> 投票結果):
// poll result
public function studentGroup(): HasOneDeep
{
return $this->hasOneDeepFromRelations($this->user(), (new User())->studentGroup());
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.