Relationships
Last updated
Last updated
[[toc]]
Database tables are often related to one another. For example, a blog post may have many comments or an order could be related to the user who placed it. Orm makes managing and working with these relationships easy, and supports a variety of common relationships:
A one-to-one relationship is a very basic type of database relationship. For example, a User
model might be associated with one Phone
model.
Orm determines the foreign key of the relationship based on the parent model name. In this case, the Phone
model is automatically assumed to have a UserID
foreign key. If you want to override this convention, you can add foreignKey
Tag to the Phone
field in User
model(Other relationships are similar):
Additionally, Orm assumes that the foreign key should have a value matching the primary key column of the parent. In other words, Orm will look for the value of the user's id
column in the UserId
column of the Phone
record. If you would like the relationship to use a primary key value other than id
, you can add references
Tag to the Phone
field in User
model. pass a third argument to the hasOne method(Other relationships are similar):
So, we can access the Phone
model from our User
model. Next, let's define a relationship on the Phone
model that will let us access the user that owns the phone. We can define a User
field in Phone
model:
A one-to-many relationship is used to define relationships where a single model is the parent to one or more child models. For example, a blog post may have an infinite number of comments. Like all other Orm relationships, one-to-many relationships are defined by defining a field on your Orm model:
Remember, Orm will automatically determine the proper foreign key column for the Comment
model. By convention, Orm will take the "hump case" name of the parent model and suffix it with ID
. So, in this example, Orm will assume the foreign key column on the Comment
model is PostID
.
Now that we can access all of a post's comments, let's define a relationship to allow a comment to access its parent post. To define the inverse of a One To Many
relationship, define a relationship method on the child model which calls the belongsTo method:
Many-to-many relations are slightly more complicated than One To One
and One To Many
relationships. An example of a many-to-many relationship is a user that has many roles and those roles are also shared by other users in the application. For example, a user may be assigned the role of "Author" and "Editor"; however, those roles may also be assigned to other users as well. So, a user has many roles and a role has many users.
To define this relationship, three database tables are needed: users
, roles
, and role_user
. The role_user
table naming can be customized and it contains user_id
and role_id
columns. This table is used as an intermediate table linking the users and roles.
Remember, since a role can belong to many users, we cannot simply place a user_id
column on the roles
table. This would mean that a role could only belong to a single user. In order to provide support for roles being assigned to multiple users, the role_user
table is needed. We can summarize the relationship's table structure like so:
We can define a Roles
field on User
model:
To define the inverse of the relationship, just define a Users
field in Role
model and append a Tag.
In general, the intermediate table foreign key are named by the "snake case" of parent model name, you can override them by joinForeignKey
, joinReferences
:
Table structure:
A polymorphic relationship allows the child model to belong to more than one type of model using a single association. For example, imagine you are building an application that allows users to share blog posts and videos. In such an application, a Comment
model might belong to both the Post
and Video
models.
A polymorphic relation is similar to a normal relation; however, the child model can belong to more than one type of model using a single association. For example, a blog Post
and a User
may share a polymorphic relation to an Image
model. Using a polymorphic relation allows you to have a single table of unique images that may be associated with posts and users. First, let's examine the table structure:
Note the imageable_id
and imageable_type
columns on the images
table. The imageable_id
column will contain the ID value of the post or user, while the imageable_type
column will contain the class name of the parent model. The imageable_type
column is used by Orm to determine which "type" of parent model to return when accessing the imageable
relation. The comments
table is similar.
Next, let's examine the model definitions needed to build this relationship:
You can change the polymorphic value by polymorphicValue
Tag, such as:
For example, imagine a blog application in which a User
model has many associated Post
models:
You can use the Select
, Omit
methods to to control the create and update of associations. These two method cannot be used at the same time and the associated control functions are only applicable to Create
, Update
, Save
:
Append new associations for Many To Many
, One To Many
, replace current association for One To One
, One To One(revers)
:
Replace current associations with new ones:
Remove the relationship between source & arguments if exists, only delete the reference, won’t delete those objects from DB, the foreign key must be NULL:
Remove all reference between source & association, won’t delete those associations:
Return the count of current associations:
Eager loading conveniences for querying multiple models, and alleviates the "N + 1" query problem. To illustrate the N + 1 query problem, consider a Book
model that "belongs to" to an Author
model:
Now, let's retrieve all books and their authors:
This loop will execute one query to retrieve all of the books within the database table, then another query for each book in order to retrieve the book's author. So, if we have 25 books, the code above would run 26 queries: one for the original book, and 25 additional queries to retrieve the author of each book.
Thankfully, we can use eager loading to reduce this operation to just two queries. When building a query, you may specify which relationships should be eager loaded using the With
method:
For this operation, only two queries will be executed - one query to retrieve all of the books and one query to retrieve all of the authors for all of the books:
Sometimes you may need to eager load several different relationships. To do so, just call the With
method multiple times:
To eager load a relationship's relationships, you may use "dot" syntax. For example, let's eager load all of the book's authors and all of the author's personal contacts:
Sometimes you may wish to eager load a relationship but also specify additional query conditions for the eager loading query. You can accomplish this as below:
In this example, Orm will only eager load posts where the post's name
column equal the word author
.
Sometimes you may need to eager load a relationship after the parent model has already been retrieved. For example, this may be useful if you need to dynamically decide whether to load related models:
If you need to set additional query constraints on the eager loading query, you can use the code as below:
To load a relationship only when it has not already been loaded, use the LoadMissing
method: