Laravel 5.3多态关系

时间:2016-12-29 10:53:28

标签: php laravel laravel-5 eloquent

我试图了解我在Laravel 5.3中的第一个多态关系。

我想要实现的关系是“编辑”和“编辑”。会有很多元素'每个元素都是自己的模型,并有一个订单。

例如,我将有一个' ElementText',' ElementImage',' ElementButton'模特然后编辑'编辑'将分配给它的各种元素。

这就是我认为我需要多态关系的原因。我不希望“编辑”中的每种元素类型都有多种关系。模特,我希望能够得到所有元素'无论其类型如何,都要按顺序排列。

我认为理念解决方案是拥有一个' editorial_element'带有

列的数据透视表
editorial_id - integer
order - integer
element_id - integer
element_type - string

类似于laravel文档中的morphToMany示例,但在该示例中,您需要指定要变形的模型。

所以我也想知道我是否应该在我的社论模型中使用morphTo()方法。

public function elements() {
    return $this->morphTo();
}

但我认为这意味着我必须将_type_id列添加到我的编辑表中,这些列将是向后的(每个编辑允许一个元素)

我是否可以设定我需要的关系,或者我接近错了?

2 个答案:

答案 0 :(得分:1)

我不认为多态关系适合这里。我可能会这样接近它。

editorials
 - id
 - title
 - etc...

elements
 - editorial_id
 - elements_id
 - elements_type

elements_image
 - id
 - url

elements_text
 - id
 - text

然后你的模特可以。

class Editorial extends Model {

    // ...

    public function elements() {
        return $this->hasMany(\Element::class);
    }

    // ...

}

class Element extends Model {

    // ...

    public function editorial() {
        return $this->belongsTo(\Editorial::class);
    }

    public function image() {
        return $this->belongsTo(\ElementImage::class, 'elements_id');
    }

    public function text() {
        return $this->belongsTo(\ElementText::class, 'elements_id');
    }

    public function content() {
        $type = $this->elements_type;
        return $this->{$type}();
    }

    // ...

}

class ElementImage extends Model {

    // ...

    public function element() {
        return $this->hasOne(\Element::class, 'elements_id');
    }

    // ...

}

class ElementText extends Model {

    // ...

    public function element() {
        return $this->hasOne(\Element::class, 'elements_id');
    }

    // ...

}

也许那时你可以让所有元素实现一个强制所有元素都有render()方法的接口,然后你可以在视图中执行此操作:

@foreach($editorial->elements as $element)
    {{ $element->content->render() }}
@endforeach

然后,渲染方法可以负责格式化和输出内容。

这一切都只是理论,我有兴趣看看你是否可以让它发挥作用,因为它是我之前试图解决的一个问题。如果您认为我的想法很愚蠢,请告诉我任何更正。

答案 1 :(得分:0)

您应该按照以下方式设置您的关系。

Editorial模型中,您应该为每个Element*模型提供方法。 E.g。

public function textElements() {
    return $this->morphedByMany(ElementText::class, 'element');
}


public function buttonElements() {
    return $this->morphedByMany(ElementButton::class, 'element');
}

Element*模型中,您应该使用以下方法来获取它变形的所有Editorials

public function editorials()
    return $this->morphToMany(Editorial::class, 'element');
}

注意:使用多态关系存在一些值得注意的问题。最重要的是,您可以在数据库结构中获得一些简单性,但同时又会丢失外键约束。这意味着,如果删除Element*,则需要删除其手动变形的任何Editorials,而在正常的Many to Many关系中,您可以设置外键约束并且RDBMS为您完成此任务。

注2:首先,我会尝试查看这些Element表是否可以统一到一个表中。如果他们能够使你的工作变得更容易。但是如果你必须使用很多Element表,我认为两种方式都可以。每个都有优点和缺点。你必须自己处理数据库一致性的许多关系表或多态关系,无论哪种方式,你都不能与$editorial->elements()建立关系。