DJZT
@DJZT
Laravel - code for you

Как реализовывать наследование моделей в laravel?

Интересует вопрос, как вы делаете наследование моделей в laravel? Например у меня есть модель User как объект хранящий в себе информацию о пароле, логине и тому-подобное. То есть в основном для авторизации всё. Далее от этой модели наследуется модель OrgAdmin - как администратор какой либо организации в приложении. В этой модели есть ссылка на саму организацию и тому подобное. Но есть и модель пользователя Profile (к примеру) которая также наследуется от User. При всём этом потомки имеют настолько разную структуру полей, что в одной таблице хранить не вариант (мне так кажется). Как в данном случае поступать? Как разбить на несколько таблиц это всё? И если это правильно, то как потом мне получить модель по id сразу собранную из 2х таблиц (users, profiles) например?

Если мой подход не правильный - то почему? Как можно обойти это всё кроме использования полиморфической связи?
  • Вопрос задан
  • 948 просмотров
Решения вопроса 1
@jacob1237
То что Вы пытаетесь реализовать, называется наследованием таблиц (Table Inheritance) - это такой способ эмулировать наследование классов в реляционных СУБД.

Всего существует несколько известных вариантов решения такой проблемы, например Single Table Inheritance и Class Table Inheritance (это если не учитывать нативную поддержку подобных вещей в некоторых СУБД, например PostgreSQL).

Полиморфные же связи (которые по-дефолту в Laravel) - это не очень хороший способ реализации, потому что не позволяет поддерживать целостность связей на уровне СУБД. Однако можно использовать и его, если Вам эта целостность не очень важна (ее надо будет поддерживать на уровне приложения).

К сожалению Eloquent не поддерживает ни Single Table Inheritance, ни Class Table Inheritance (зато их поддерживает Doctrine из Symfony), поэтому придется писать вручную.

Прежде чем это делать, я бы Вам посоветовал разобраться как Profile относится к User и OrgAdmin.
Является ли Profile подвидом пользователя (из названия честно говоря не понял), или же это просто набор дополнительных полей, которые можно оформить в виде связей?

Если и Profile и OrgAdmin - это подвиды (подтипы) пользователей со своим собственным набором полей, то Вам нужно добавить в общую таблицу отдельное поле type (это называется дискриминатор), в котором у Вас будет проставлен тип пользователя. Например 1 для User, 2 для Profile и 3 для OrgAdmin.
Короче очень похоже на стандартный Polymorphic Relationships из Laravel.

А потом переопределяете у модели User функции newFromBuilder() или newInstance() в которых Вы укажете какие классы моделей создавать для конкретного type. Вот например статья.

Дальше для Class Table Inheritance можно в трейт поместить функцию сохранения и родителя и потомка, потому что сохранять их придется вместе (на уровне БД), в зависимости от измененных свойств. Кроме того, нужно будет позаботиться об отображении (mapping) атрибутов родителя на потомков (__set и __get), на случай если вдруг захочется делать вот так (представьте что атрибут name принадлежит родителю - модели User):
$profile = new Profile();
$profile->name = 'John Doe';
$profile->save();


Короче это гемор в Laravel. Поэтому перед тем как делать, подумайте можно ли решить задачу проще - например через Single Table Inheritance, поместив все атрибуты в одну таблицу, либо делайте через стандартные полиморфные связи.

Когда я решал эту задачу, я все вышеуказанные функции помещал в трейты. Может когда-нибудь дойдут руки запилить отдельную библиотеку или отправить патч в само ядро фреймворка.

Погуглите по указанным ключевым словам (паттернам), может что уже появилось для Laravel.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
xpert13
@xpert13
Full Stack Developer
Если модели настолько разные, то может вообще не наследоваться от User, а просто связывать их через relationships (один к одному)?

Т.е. OrgAdmin отдельная модель связанная через relationships с User и Profile отдельная модель связаная через relationships с User. В таком случае у вас всё будет в разных таблицах и найти из одной модели другую не составит труда.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы