Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Страницы 1
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)
Не в сети
Если таблица одна, то и модель лучше одну иметь а по типам можно фильтровать вручную, либо с помощью локальных заготовок (local scopes):
Element::type(self::TYPE_SOMETHING)->get()
Или сделать для каждого типа отдельный метод:
Element::someType()->get()
Если хочется использовать отдельные модели, то все будет работать, но думаю, что дублированного кода в итоге будет очень много.
Не в сети
Если таблица одна, то и модель лучше одну иметь а по типам можно фильтровать вручную, либо с помощью локальных заготовок (local scopes):
С фильтрацией проблем нет, проблема в том, что в таблице хранятся похожие сущности, но разных типов, над ними надо совершать какие то похожие, но всё таки отличающиеся манипуляции.
Скажем есть в модели метод getSize(), но логика работы разная для элементов с разными типами и получается такая штука:
public function getSize()
{
if ($this->type === 'typeA') {
return ....;
} elseif ($this->type === 'typeB') {
return ....;
} elseif (...) { ... }
}
И так в десятке методов. Потом у нас появляется еще несколько типов и приходится в десятке методов отредактировать условные операторы... А если применить наследование, то каждый тип имел бы свою реализацию getSize() и других необходимых методов, а остальное поведение наследовал.
Как правило требуется получать коллекцию со всеми элементами и что то сделать с каждым. Например вызывать какой то метод элемента.
Не в сети
Как правило требуется получать коллекцию со всеми элементами и что то сделать с каждым. Например вызывать какой то метод элемента.
$model->getService()->getSize();
где getService - фабрика, которая на основе атрибутов возвращает необходимую реализацию.
Будет куча проблем, если все же захочешь наследование моделей.
Не в сети
логика работы разная для элементов с разными типами
Ну тогда наследование делай, либо просто отдельные модели. Но я бы это делал только в крайнем случае.
Не в сети
Понятно. Спасибо.
Не в сети
Страницы 1