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 столбцы в мою таблицу редакционных статей, которая была бы обратной (позволяя один элемент на редакционную статью)



Есть идеи, могу ли я установить нужные мне отношения или я неправильно к ним подхожу?

645   2  

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

    Ничего не найдено.