簡體   English   中英

如何在 Laravel 中設置 Eloquent 關系屬於通過另一個模型?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM