Laravel 5.3 полиморфные отношения
Я пытаюсь получить мою голову вокруг мои первые полиморфные отношения в фреймворк Laravel 5.3.
Отношение, которого я пытаюсь достичь, состоит в том, что "редакционная статья" будет иметь много "элементов", каждый из которых будет иметь свою собственную модель и порядок.
Так, например, у меня будет "ElementText", "ElementImage", "ElementButton", а затем "Editorial" будет иметь различные элементы, назначенные ему.
Вот почему я думаю, что мне нужна полиморфная связь. Я не хочу множественных отношения для каждого типа элемента в модели "Editorials", я хочу иметь возможность просто получить все "элементы" независимо от его типа и получить его в порядке.
Я думаю, что идея решения заключалась бы в том, чтобы иметь сводную таблицу editorial_element с такими столбцами, как
editorial_id - integer
order - integer
element_id - integer
element_type - string
Аналогично примеру morphToManyв документах laravel, но в этом примере необходимо указать модель для морфинга.
Поэтому я также задался вопросом, следует ли мне использовать метод morphTo() в моих редакционных статьях модель.
public function elements() {
return $this->morphTo();
}
Но я думаю, что это означает, что я должен был бы добавить _type и _id столбцы в мою таблицу редакционных статей, которая была бы обратной (позволяя один элемент на редакционную статью)
Есть идеи, могу ли я установить нужные мне отношения или я неправильно к ним подхожу?
2 ответов:
Я не думаю, что полиморфные отношения будут хорошо подходить здесь. Я мог бы подойти к этому так.
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Затем метод render может отвечать за форматирование и вывод содержимого.
Это все только теория, мне было бы интересно посмотреть, сможете ли вы это сделать. работать, потому что это проблема, которую я пытался решить и раньше. Пожалуйста, дайте мне знать о любых исправлениях или если вы считаете, что моя идея просто глупа.
Вы должны настроить свои отношения, как показано ниже.
В вашей модели
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вы можете установить ограничение внешнего ключа, и СУБД сделает это за вас.Примечание 2: прежде всего я хотел бы попытаться увидеть, могут ли эти таблицы элементов быть объединены в одну таблицу. Если бы они могли, ваша работа стала бы намного проще. Но если вам нужно использовать много таблиц элементов, я думаю, что оба способа хороши. У каждого из них есть преимущество и disadvantage.It есть много таблиц отношений или полиморфных отношений, которые вы должны обрабатывать согласованность базы данных самостоятельно, и в любом случае вы не можете сделать
$editorial->elements()с отношением.
Comments