Laravel notes-eloquent ORM (associated relationship)
It 's written in front .
time is valuable, use the catalogue ↑
Learn Laravel notes, just as Laravel document notes, the purpose is to strengthen the understanding of the document, the quality is not high. What is an association relationship
So, there is bound to be some connection between tables and tables in a database, which is the meaning of correlation.
Through eloquent we can easily handle these relationships. Defining an association relationship One-on-one
For example, a user will have a mobile phone, this one-to-one relationship we directly define a phone method in user is OK.
namespace App;
Use Illuminate\database\eloquent\model;
Class User extends model{
/**
* Get the user's cell phone
/Public Function phone ()
{return
$this-> Hasone (' App\phone ');
In this example, the phone model defaults to a user_id foreign key,
//If you wish to override this Convention, you can pass the second argument to the Hasone method. return
$this->hasone (' App\phone ', ' Foreign_key ');
/*eloquent assumes that the foreign key should have a matching ID on the parent, in other words, eloquent will go through the ID value of the user table to the phone table to query the phone records that match user_id. If you want to associate a relationship with another value instead of an ID, you can pass the third parameter to Hasone to specify a custom primary key:
/return $this->hasone (' App\phone ', ' foreign_key ', ' Local_ Key ');
Frankly speaking is Hasone (' Association eloquent ', ' the key of the linked table ', ' This Table key ')
}}
When used:
So you can get a case of phone
$phone = user::find (1)->phone;
Relative Correlation
Once a one-to-one relationship is over, we'll think that user can now find phone, so how do we find user in phone?
method is similar to the above:
namespace App;
Use Illuminate\database\eloquent\model;
Class Phone extends model{
/**
* Get the phone's corresponding
user
/Public function user ()
{
/*,eloquent The user model will be tried to find a matching record through the phone model's user_id. Eloquent generates the default foreign key name by associating the relational method name and adding the _id suffix after the method name. * * Return
$this->belongsto (' App\user ');
parameter is similar to the above one-to-one
}
}
A pair of many
For example, a blog will have more than one comment. Hasmany
Access comments through articles.
namespace App;
Use Illuminate\database\eloquent\model;
Class Post extends model{
/**
* Get comments on blog posts
*
/Public Function Comments ()
{
// Similar hasone exist with the following parameters return
$this->hasmany (' app\comment ', ' foreign_key ', ' Local_key ');
}
one-to-many (reverse)
Access the article through comments. Belongsto
namespace App;
Use Illuminate\database\eloquent\model;
Class Comment extends model{
/**
* get comment corresponding blog article
/public
function post ()
{return
$this-> Belongsto (' App\post ', ' foreign_key ', ' Other_key ');
}
many to many
A user has multiple roles, while a role is shared by multiple users. For example, many users may have an "Admin" role. To define such an association, you need three datasheets: users, roles, and Role_user,role_us
The ER table is named alphabetically by the associated model name and contains the user_id and role_id two columns.
Belongstomany
The two-table data is a many-to-many relationship.
A table of data in table B can be found in a number of data, B table data can also be found in table a more than one data.
Of course, the two-table relationship is organized through an intermediate table.
The default naming method for the intermediate table is: A_b, you can modify
The inverse Association of many to many is the same as the positive direction.
Use the example above:
for user
namespace App;
Use Illuminate\database\eloquent\model;
Class User extends model{
/**
* User role/Public
function roles ()
{
//You can see the first one is the associated table, the middle table, the key, the key return
$this->belongstomany (' app\role ', ' user_roles ', ' user_id ', ' role_id ');
}
For role as well.
namespace App;
Use Illuminate\database\eloquent\model;
Class role extends model{
/**
* Roles user
/Public Function users ()
{return
$this-> Belongstomany (' App\user ');
}
about the middle table
The above mentioned the middle table, here to expand:
If we want to access the data in the middle table, we can use the Pivot property, and he gets an instance of the middle table.
$user = App\user::find (1);
foreach ($user->roles as $role) {
echo $role->pivot->created_at;
}
Of course, by default by pivot we can only access the association key, which is the user_id and role_id of the example above.
To access other columns, such as the created_at above, need to be defined at the time of association.
The following methods are defined:
If you want to get Column1,column2 return
$this->belongstomany (' App\role ')->withpivot (' Column1 ', ' column2 ');
If you want to get Created_at and Updated_at return
$this->belongstomany (' App\role ')->withtimestamps ();
At the same time, we can use the Wherepivot and Wherepivotin methods to filter the result set when associating.
Intermediate table records are required to conform to approved=1. return
$this->belongstomany (' App\role ')->wherepivot (' approved ', 1);
The intermediate table records are required to conform to priority in 1,2. return
$this->belongstomany (' App\role ')->wherepivotin (' Priority ', [1, 2]);
more than a pair of far layers
Always feel ' far layer ' wrong typo ...
For example, a school classmate Tom sent an article,
The school table, the student table, the article table relationship is like this:
Schools <-> Students <-> articles
So the school is very article has no direct correlation. But there is a correlation between students.
So when we search through the school articles, we need to use a far-level association.
namespace App;
Use Illuminate\database\eloquent\model;
Class School extends model{
/**
* Access to all articles of the specified school
/Public Function posts ()
{
//final associated model, intermediate model, The foreign key of the intermediate model, the foreign key of the final model return
$this->hasmanythrough (' app\post ', ' app\student ', ' country_id ', ' user_id ');
}
Polymorphic Association
Users can either comment on the article or comment on the video, using a polymorphic association, where you can use a single comments table in both scenarios.
Two important columns to note are the commentable_id and Commentable_type on the comments table. The commentable_id column corresponds to the ID value of the Post or video, and the Commentable_type column corresponds to the class name of the owning model. When accessing the Commentable Association, ORM determines the type of the owning model according to the Commentable_type field and returns the corresponding model instance.
Using Morphto in the associated table ()
namespace App;
Use Illuminate\database\eloquent\model;
Class Comment extends Model
{/** * get all of the
owning commentable models.
*/Public
function commentable ()
{return
$this->morphto ();
}
}
Class Post extends Model
{/** * get all of the
Post ' s comments.
*/Public
function Comments ()
{return
$this->morphmany (' app\comment ', ' commentable ');
}
class Video extends Model
{/** * Get all of the video
' s comments.
*/Public
function Comments ()
{return
$this->morphmany (' app\comment ', ' commentable ');
}
Use:
$post = App\post::find (1);
foreach ($post->comments as $comment) {
//
}
//or directly remove the corresponding instance
$commentable = $comment-> commentable;
Customizing polymorphic types
There is a commentable_type this column, which is assigned in the above method: App\post or App\video.
We can also customize him by using the Morphmap method to:
Use illuminate\database\eloquent\relations\relation;
Relation::morphmap ([
' posts ' => app\post::class,
' videos ' => app\video::class,
]);
Of course, we need to register this morphmap with the service provider, for example, the common Appserviceprovider many-to-many Polymorphism Association
In addition to the traditional polymorphic associations, you can also define "many-to-many" polymorphism associations, for example, a blog post and video model might share a tag model's polymorphic association. Using pairs of polymorphic associations allows you to have a unique list of tags between blog posts and videos.
Table structure:
Posts
id-integer
name-string
videos
id-integer
name-string
tags
id-integer
Name-string
taggables
tag_id-integer
taggable_id-integer
taggable_type-string
The first step is to add the Morphtomany method in post and videos:
namespace App;
Use Illuminate\database\eloquent\model;
Class Post extends model{
/**
* Get the specified article all
tags
/Public Function tags ()
{return
$this-> Morphtomany (' App\tag ', ' taggable ');
}
namespace App;
Use Illuminate\database\eloquent\model;
Class Video extends model{
/**
* Get the specified article all
tags
/Public Function tags ()
{return
$this- >morphtomany (' App\tag ', ' taggable ');
}
Then each association model in the tag model defines a method, for example, we define a posts method and a videos method:
namespace App;
Use Illuminate\database\eloquent\model;
Class Tag extends model{
/**
* Gets all articles assigned to this label
/Public Function posts ()
{return
$this- >morphedbymany (' App\post ', ' taggable ');
}
/**
* Get all videos that assign this label
/Public Function videos ()
{return
$this->morphedbymany (' App\ Video ', ' taggable ');
}
When used:
$post = App\post::find (1);
foreach ($post->tags as $tag) {
//
}
//
$tag = App\tag::find (1);
foreach ($tag->videos as $video) {
//
}
Association Query
Basic Query
In fact, the above has been used, that is, when the relationship is established, we can quickly get other instances of it associated with one of the instances.
For example, the post and user mentioned above
First get a user
$user = app\user::find (1);
By association or his post
$user->posts ()->where (' active ', 1)->get ();
Of course, if you do not need to filter the Post through other constraints, you can use the attribute directly to access the corresponding user
$user = App\user::find (1);
foreach ($user->posts as $post) {
//
}
to constrain by association relationship
Sometimes you may want to get at least one comment post.
At this point, if you establish an association of two tables, you can filter by using the Has method:
/* Comments is the associated method
//Get all articles with at least one comment ...
$posts = App\post::has (' comments ')->get ();
Get all articles with at least three reviews ...
Association method, comparison character, numeric
$posts = Post::has (' comments ', ' >= ', 3)->get ();
Get all the articles that have at least one comment to get the vote.
Use. To nest has:post<->comment<->vote
$posts = Post::has (' comments.votes ')->get ();
Get all articles with at least one comment containing foo words
//Use closure functions to implement advanced queries, as well as for Orwherehas ()
$posts = Post::wherehas (' Comments ', function ($ Query) {
$query->where (' content ', ' like ', ' foo% ');
} ->get ();
Of course, you can also query the post without comment,
is the reverse selection of the above option.
$posts = app\post::d oesnthave (' comments ')->get ();
$posts = Post::wheredoesnthave (' Comments ', function ($query) {
$query->where (' content ', ' like ', ' foo% ');
} ->get ();
Statistical correlation Model
This means that only the number of the associations is not getting specific information
Simple similar to this:
$posts = App\post::withcount (' comments ')->get ();
foreach ($posts as $post) {
echo $post->comments_count;
}
You can add a "count" of multiple associated relationships as you add constraints to a query:
$posts = Post::withcount ([' votes ', ' comments ' => function ($query) {
$query->where (' content ', ' like ', ' foo% ') ;
}]) ->get ();
echo $posts [0]->votes_count;
Echo $posts [0]->comments_count;
Eager loading
The first thing to figure out is what a craving load is lazy loading .
With examples of users and books:
Lazy Loading: Search the user first, and then search for the book each time you request a book.
eager to load: actively search for his articles when searching for users
If you search for 20 users, the number of searches is 2.
SELECT * from user where age > 20
SELECT * from book where user_id in (1, 2, 3, 4, 5, ...)
So when you have to get the associated item, you can use a craving load:
Use with to set up a craving-loaded association
$users = app\user::with (' book ')->get ();
foreach ($users as $user) {
echo $user->book->title;
}
If you want to load multiple:
$users = App\user::with (' book ', ' Phone ')->get ();
If nested association: book's publisher
$users = App\user::with (' book.press ')->get ();
A conditional constraint-hungry load
//title must contain the
$users = App\user::with ([' Book ' => function ($query) {
$query->where (' title ', ' Like ', '%first% ');
}] ->get ();
Sometimes, we need to do a craving load on an association of an instance that has been lazy loaded.
Use the Load method to implement:
$users = App\user::all ();
if ($someCondition) {
$users->load (' book ', ' phone ');
}
$users->load ([' Book ' => function ($query) {
$query->orderby (' published_date ', ' ASC ');
}];
Insert & Update
For example, you may need to insert a new comment to the post model, and you can insert the comment directly from the relational Save method instead of manually setting the comment post_id attribute
Make incoming updates more convenient:
Feel This example a bit silly
$comment = new App\comment ([' Message ' => ' A new comment.]);
$post = App\post::find (1);
$post->comments ()->save ($comment);
Save multiple
$post->comments ()->savemany ([
New App\comment ([' Message ' => ' A new Comment.]),
new app\ Comment ([' Message ' => ' Another Comment. '])
;
You can also use the Create
$post = App\post::find (1);
$comment = $post->comments ()->create ([
' message ' => ' A new comment. ',
]);
Reverse Update
At this time I started my own name, the parent model of the above update the child model I think is a forward update.
So updating the parent model through the child model I think is a reverse update.
It always feels a little wrong. (How to say ...) Reverse binding. )
is actually the way to update the Belongsto association:
Use the Associate method:
$account = App\account::find (ten);
$user->account ()->associate ($account);
$user->save ();
Remove Belongsto Association:
$user->account ()->dissociate ();
$user->save ();
Multi-Many-to-many Association
A many-to-many relationship has already been said, because there is an intermediate table, so it must be more complex.
Additional
For example, to give a user a new identity. Complete using the Attach method:
Access to user
$user = app\user::find (1);
Attach an identity to the user
$user->roles ()->attach ($roleId);
You can also pass additional fields
$user->roles ()->attach ($roleId, [' Expires ' => $expires]);
In fact, in the middle of the table is to insert a user and identity relationship.
Separation
is to delete an identity of a user:
Remove role
from specified user ... $user->roles ()->detach ($roleId);
Remove all roles
from the specified user ... $user->roles ()->detach ();