Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 04.02.2018 22:51:51

Наследование моделей

Laravel 5.3.31, PHP 7.1.13

Есть таблица Elements. Сущности в этой таблице имеют определенные типы, хранимые в поле type, от типа зависит поведение элемента. Например отличается логика в некоторых методах модели. Это сейчас сделано через условные операторы, что не удобно.

Хочется как то унифицировать работу с элементами, чтобы она происходила через один интерфейс, этого можно было бы достичь наследованием. То есть от модели Element унаследовать ElementOfTypeA, ElementOfTypeB, ... и реализовать в каждом по своему определенные методы.

Но проблема в том, что непонятно как это сделать и вообще возможно ли это сделать, чтобы можно было работать со всем этим через eloquent.

То есть, если нужно получить все элементы и обратиться к какому то методу каждого из них, то нельзя просто сделать

Element::all()

поскольку в полученной коллекции тип всех элементов окажется родительский - Element и, соответственно, обращения пойдут к методам родительского класса.

В идеале, я вижу такое решение: при запросах на получение (вроде ::all()) к модели Element как то заставить eloquent создавать объекты нужного типа основываясь на значении хранимом в поле type таблицы Elements.

Есть ли такой способ?
Или, возможно, есть более подходящая архитектура для такого кейса?



(похожая ситуация рассматривается в https://habrahabr.ru/post/344728/ но там не приводятся решения для описанной мной проблемы: как получать от eloquent объекты разного типа?).

Изменено Silm (05.02.2018 10:24:30)

Не в сети

#2 05.02.2018 13:23:01

Re: Наследование моделей

Если таблица одна, то и модель лучше одну иметь а по типам можно фильтровать вручную, либо с помощью локальных заготовок (local scopes):

Element::type(self::TYPE_SOMETHING)->get()

Или сделать для каждого типа отдельный метод:

Element::someType()->get()

Если хочется использовать отдельные модели, то все будет работать, но думаю, что дублированного кода в итоге будет очень много.

Не в сети

#3 05.02.2018 14:59:58

Re: Наследование моделей

Если таблица одна, то и модель лучше одну иметь а по типам можно фильтровать вручную, либо с помощью локальных заготовок (local scopes):

С фильтрацией проблем нет, проблема в том, что в таблице хранятся похожие сущности, но разных типов, над ними надо совершать какие то похожие, но всё таки отличающиеся манипуляции.

Скажем есть в модели метод getSize(), но логика работы разная для элементов с разными типами и получается такая штука:

public function getSize()
{
  if ($this->type === 'typeA') {
    return ....;
  } elseif ($this->type === 'typeB') {
    return ....;
  } elseif (...) { ... }
}

И так в десятке методов. Потом у нас появляется еще несколько типов и приходится в десятке методов отредактировать условные операторы... А если применить наследование, то каждый тип имел бы свою реализацию getSize() и других необходимых методов, а остальное поведение наследовал.

Как правило требуется получать коллекцию со всеми элементами и что то сделать с каждым. Например вызывать какой то метод элемента.

Не в сети

#4 05.02.2018 18:33:18

Re: Наследование моделей

Как правило требуется получать коллекцию со всеми элементами и что то сделать с каждым. Например вызывать какой то метод элемента.

$model->getService()->getSize();

где getService - фабрика, которая на основе атрибутов возвращает необходимую реализацию.

Будет куча проблем, если все же захочешь наследование моделей.

Не в сети

#5 05.02.2018 18:38:59

Re: Наследование моделей

логика работы разная для элементов с разными типами

Ну тогда наследование делай, либо просто отдельные модели. Но я бы это делал только в крайнем случае.

Не в сети

#6 05.02.2018 18:49:30

Re: Наследование моделей

Понятно. Спасибо.

Не в сети

Подвал раздела