2016-12-29 120 views
2

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

我试图实现的关系是'编辑'将有许多'元素'每个元素将是它自己的模型,并有一个顺序。因此,例如我将有一个'ElementText','ElementImage','ElementButton'模型,然后'编辑'将有不同的元素分配给它。

这就是为什么我认为我需要一个多态关系。我不想在'Editorials'模型中为每个元素类型创建多个关系,我希望能够获取所有'Elements',而不管其类型如何,并按顺序获取它。

我认为这个想法的解决办法是有一个与列的“editorial_element”数据透视表像

editorial_id - integer 
order - integer 
element_id - integer 
element_type - string 

类似于laravel文档的morphToMany的例子,但在这个例子,你需要指定模型变形。

所以我也想知道如果我应该在我的编辑模型中使用morphTo()方法。

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

但我认为,这意味着我将不得不_type_id列添加到我的社论表这将是向后(允许每个编辑一个元素)

任何想法,如果我可以将我需要的关系或者我接近它错了?

回答

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 

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

这都只是理论,我很想看看你是否能够得到这个工作,因为这是我以前试图解决的问题。请让我知道任何更正,或者如果你认为我的想法是愚蠢的。

+0

我明白了,我是否认为'元素'模型需要手动更新并且不再接受使用这种方法的attach(),detach()方法? –

+0

'BelongsTo()'有'associate()'和'disassociate()',但我想不出你创建它们后会操纵这些关系的情况。我唯一能看到的变化就是'编辑 - hasMany - Element',不幸的是似乎没有'sync()'方法,但你可以'saveMany()'。 –

+0

在早点下班回家之前,我很快就采取了这种方法。我没有使用视图,但做了以下工作 $ editorial = \ App \ Editorials :: with('elements') - > first(); ($ editorial-> elements as&$ elements){ \t \t $ elements-> content; \t}。 不知道它是如何影响性能的。 –

0

你应该如下设置你的关系。

在您的Editorial模型中,您应该为每个Element*模型生成方法。例如。

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表格,我认为这两种方式都很好。每种方法都有优势和劣势。它有许多关系表或多态关系,您必须自己处理数据库一致性,并且无论哪种方式,您都不能在关系中执行$editorial->elements()

+0

所以你认为唯一的解决方案是在社论模型中对每种元素类型都有多种关系?理想情况下,我只想要一个“元素”关系,将他们全部带入。 –

+1

@VinceLowe编辑我的答案。阅读笔记2 –

+0

@FarzinFarzanehnia嘿,你介意查看我的答案吗?只是好奇看到你的想法。 –