如何设置Eloquent关系属于通过Laravel的另一个模型?

时间:2014-10-12 17:31:00

标签: php laravel eloquent

我有一个模型通过其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->名称,而不是$ listing-> manufacturer-> name。这引发了一个错误。我在清单模型中尝试了注释掉的2行只是为了获得效果,然后我可以回显$ 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');
    }

3 个答案:

答案 0 :(得分:9)

我找到了一个解决方案,但它并不是非常直接的。我在下面发布了它,但我发布了我认为最好的解决方案。

您不应该直接从列表中访问制造商,因为制造商仅适用于该模型。虽然您可以从列表对象中急切加载制造商关系,但请参阅下文。

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');

创建的查询
select * from `manufacturers` where `manufacturers`.`id` in (?)

?将替换为列表表格中manufacturer_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')          - >加入('制造商',' manufacturers.id',' =',' models.manufacturer_id')          - >(DB ::原始('制造商*'));选择

得到了

的查询
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模型并手动创建关系。

重要的是要注意,保存不起作用

$listing = Listing::find(1);
$listing->manufacturer()->associate(Manufacturer::create([]));
$listing->save();

这将创建一个新的制造商,然后将listings.model_id更新为新制造商的ID。

答案 1 :(得分:1)

你可以这样做(学生组 -> 用户 -> 投票结果):

// poll result

    public function studentGroup(): HasOneDeep
    {
        return $this->hasOneDeepFromRelations($this->user(), (new User())->studentGroup());
    }

答案 2 :(得分:0)

我想这会有所帮助,对我有帮助:

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();
    }
}

至少,正是这种需要让我想到了一个beforeToThrough