S
S
Stanislav Pochepko2016-11-22 15:16:12
Laravel
Stanislav Pochepko, 2016-11-22 15:16:12

How to implement model inheritance in laravel?

Interested in the question, how do you do model inheritance in laravel? For example, I have a User model as an object that stores information about a password, login, and the like. That is basically everything for authorization. Further, the OrgAdmin model is inherited from this model - as an administrator of any organization in the application. In this model, there is a link to the organization itself and the like. But there is also a user model Profile (for example) which is also inherited from User. With all this, the descendants have such a different field structure that it is not an option to store in one table (I think so). How to proceed in this case? How to split this into several tables? And if this is correct, then how can I get a model by id immediately assembled from 2 tables (users, profiles) for example?
If my approach is wrong, then why? How can I get around all this other than using a polymorphic relationship?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
J
jacob1237, 2016-11-22
@DJZT

What you're trying to implement is called Table Inheritance, which is a way to emulate class inheritance in relational DBMSs.
In total, there are several well-known solutions to this problem, for example, Single Table Inheritance and Class Table Inheritance (this is not taking into account the native support for such things in some DBMS, such as PostgreSQL).
Polymorphic relationships (which are default in Laravel) are not a very good way to implement, because they do not allow maintaining the integrity of relationships at the DBMS level. However, you can use it if this integrity is not very important to you (it will need to be supported at the application level).
Unfortunately, Eloquent does not support either Single Table Inheritance or Class Table Inheritance (but Doctrine from Symfony supports them), so you have to write it manually.
Before doing this, I would advise you to understand how Profile relates to User and OrgAdmin.
Is Profile a subspecies of the user (to be honest, I didn’t understand from the name), or is it just a set of additional fields that can be formatted as links?
If both Profile and OrgAdmin are subtypes (subtypes) of users with their own set of fields, then you need to add a separate type field to the common table (this is called a discriminator), in which you will have a user type. For example 1 for User, 2 for Profile and 3 for OrgAdmin.
In short, it is very similar to the standard Polymorphic Relationships from Laravel.
And then you override the newFromBuilder() or newInstance() functions of the User model in which you specify which model classes to create for a particular type . Here is an article for example .
Further, for Class Table Inheritance, you can put the save function of both the parent and the child in the trait, because they will have to be saved together (at the database level), depending on the changed properties. In addition, you will need to take care of mapping (mapping) the attributes of the parent to the children (__set and __get), in case you suddenly want to do this (imagine that the name attribute belongs to the parent - the User model ):

$profile = new Profile();
$profile->name = 'John Doe';
$profile->save();

In short, this is a hemorrhoid in Laravel. Therefore, before doing it, think about whether it is possible to solve the problem easier - for example, through Single Table Inheritance, placing all attributes in one table, or do it through standard polymorphic relationships.
When I solved this problem, I put all the above functions into traits. Maybe someday they will get around to writing a separate library or sending a patch to the core of the framework itself.
Google for the specified keywords (patterns), maybe something has already appeared for Laravel.

A
Alexander, 2016-11-22
@xpert13

If the models are so different, can they not be inherited from User at all, but simply connect them through relationships ( one to one )?
Those. OrgAdmin is a separate model connected through relationships with User and Profile is a separate model connected through relationships with User. In this case, you will have everything in different tables and it will not be difficult to find another from one model.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question