2016-12-29 200 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嘿,你介意查看我的答案嗎?只是好奇看到你的想法。 –