OneToOne assume that the User model is associated with the Phone model. to define such an association, you must define a phone method in the User model. this method returns an association relation defined by the hasOne method.
One To One
Assume that the User model is associated with the Phone model. to define such an association, you must define a phone method in the User model. this method returns an Association defined by the hasOne method.
hasOne('App\Phone'); }}
The first parameter of the hasOne method is the model to be associated. after being defined, you can use the following syntax to query the associated attributes.
$phone = User::find(1)->phone;
Eloquent assumes that the associated foreign key is based on the model name. Therefore, the Phone model uses the user_id field as the foreign key automatically. you can use the second parameter and the third parameter to overwrite
return $this->hasOne('App\Phone', 'foreign_key');return $this->hasOne('App\Phone', 'foreign_key', 'local_key');
Define inverse relationship
After defining the above model, you can use the User model to obtain the Phone model. of course, you can also use the Phone model to obtain the corresponding User. This uses the belongsTo method.
belongsTo('App\User'); // return $this->belongsTo('App\User', 'foreign_key'); // return $this->belongsTo('App\User', 'foreign_key', 'other_key'); }}
One To Many
Suppose there is a post with a lot of associated comments. in this case, we should use one-to-many associations and use the hasMany method.
hasMany('App\Comment'); }}
Query operations
$comments = App\Post::find(1)->comments;foreach ($comments as $comment) { //}$comments = App\Post::find(1)->comments()->where('title', 'foo')->first();
Define reverse Association
Reverse Association also uses the belonsto method. for details, refer To the One To One section.
$comment = App\Comment::find(1);echo $comment->post->title;
Failed To renew
Multi-to-multi-join because an intermediate table is added, the implementation is more complex than hasOne and hastwo.
In such a scenario, a user can belong to multiple roles, and a role can also belong to multiple users. This introduces three tables: users, roles, and role_user. The role_user table is an associated table, which contains two fields: user_id and role_id.
The belongsToMany method is required for many-to-many associations.
BelongsToMany ('app \ role', 'role _ user'); // specify the joined table, joined field // return $ this-> belongsToMany ('app \ role ', 'role _ user', 'User _ id', 'role _ id'); return $ this-> belongsToMany ('app \ role ');}}
The preceding definition defines that a user belongs to multiple roles. Once the relationship is established, you can query
user = App\User::find(1);foreach ($user->roles as $role) { //}$roles = App\User::find(1)->roles()->orderBy('name')->get();
Reverse Association
The implementation of reverse and forward relationships is the same.
belongsToMany('App\User'); }}
Retrieve the column value of the intermediate table
An intermediate table is introduced for many-to-many relationships. Therefore, you must have a method to query the column values of the intermediate table, such as the time when the relationship was established. you can use the correlated attribute to query the intermediate table.
$user = App\User::find(1);foreach ($user->roles as $role) { echo $role->pivot->created_at;}
The above code accesses the created_at field of the intermediate table.
Note that by default, the model key can be accessed through the Keys object. if the intermediate table contains additional attributes, use the withnames method to specify a column name.
return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');
Has Upload Through
This relationship is strong. assume that the Country model contains multiple User models, and each User model contains multiple Post models. that is to say, a Country has many users, these users have Many posts. we want to query all posts in a country. how can we achieve this? this uses the Has too Through relationship.
countries id - integer name - stringusers id - integer country_id - integer name - stringposts id - integer user_id - integer title - string
As you can see, the posts table does not directly contain country_id, but it establishes a relationship with the countries table through the users table.
Use the Has Upload Through link
namespace App;use Illuminate\Database\Eloquent\Model;class Country extends Model{ /** * Get all of the posts for the country. */ public function posts() { // return $this->hasManyThrough('App\Post', 'App\User', 'country_id', 'user_id'); return $this->hasManyThrough('App\Post', 'App\User'); }}
The first parameter of hasManyThrough is the name of the model we want to access, and the second parameter is the name of the intermediate model.
HasManyThrough hasManyThrough( string $related, string $through, string|null $firstKey = null, string|null $secondKey = null, string|null $localKey = null)
Polymorphic Relations)
Multi-State Association allows the same model to belong to multiple different models using one association. In this scenario, we have a post table and a comment table, users can perform operations they like on posts or comments. what should they do in this case?
The table structure is as follows:
posts id - integer title - string body - textcomments id - integer post_id - integer body - textlikes id - integer likeable_id - integer likeable_type - string
We can see that the likeable_type field in the likes table is used to determine whether the record prefers post or comment, and the table structure is available. next we will define the model.
morphTo(); }}class Post extends Model{ /** * Get all of the product's likes. */ public function likes() { return $this->morphMany('App\Like', 'likeable'); }}class Comment extends Model{ /** * Get all of the comment's likes. */ public function likes() { return $this->morphMany('App\Like', 'likeable'); }}
By default, the likeable_type type is the complete name of the associated model, for example, App \ Post and App \ Comment.
Generally, we may use a custom value to identify the associated table name. Therefore, we need to customize this value, we need to register the association in the boot method of the service provider object of the project, suchAppServiceProvider
In the boot method
use Illuminate\Database\Eloquent\Relations\Relation;Relation::morphMap([ 'posts' => App\Post::class, 'likes' => App\Like::class,]);
Search for Polymorphism
Access all the favorites of a post
$post = App\Post::find(1); foreach ($post->likes as $like) { //}
Access a favorite post or comment
$like = App\Like::find(1); $likeable = $like->likeable;
In the above example, the returned likeable will return the post or comment based on the record type.
Multi-to-many multi-state association
Multiple-to-many Association methods: morphToMany and morphedByMany. there is not much nonsense here.
Link query
In Eloquent, all links are defined using functions. you can obtain associated instances without executing Association queries. Suppose we have a blog system. The User model is associated with many Post models:
/** * Get all of the posts for the user. */public function posts(){ return $this->hasMany('App\Post');}
You can query the association and add additional constraints as follows:
$user = App\User::find(1);$user->posts()->where('active', 1)->get();
If you do not need to add constraints to the associated attributes, you can directly access the attributes of the model. for example, in the preceding example, we can use the following method to access the Post
$user = App\User::find(1);foreach ($user->posts as $post) { //}
Dynamic attributes are delayed loading. they are used to query databases only when they are accessed. they correspond to pre-loading. the pre-loading function can be used to query all data by association, reduce the number of SQL statements executed.
Query link existence
The has Method can be used to return results based on the relational existence.
// Retrieve all posts with at least one comment... $ posts = App \ Post: has ('comments')-> get (); // Retrieve all posts that have three or more comments... $ posts = Post: has ('comments', '> =', 3)-> get (); // Retrieve all posts that have at least one comment with votes... $ posts = Post: has ('comments. votes ')-> get ();
If you need more powerful functions, you can use the whereHas and orWhereHas methods to place the where condition in the has statement.
// Retrieve all posts with at least one comment matching foo % $ posts = Post: whereHas ('comments', function ($ query) {$ query-> where ('content', 'like', 'foo % ') ;})-> get ();
Pre-load
When accessing the Eloquent model, by default, all the associations are loaded with delay and will start loading only when used. This causes the need to execute a large number of SQL statements, you can use the pre-loading function to query all results using Association.
belongsTo('App\Author'); }}
Next we will retrieve all the books and their authors.
$books = App\Book::all();foreach ($books as $book) { echo $book->author->name;}
The above query will execute a query to query all the books, and then execute N queries to query the author information during traversal. Obviously, this is very inefficient, fortunately, we also have the pre-loading function, which can reduce N + 1 queries to 2 queries. during the query, we can use the with method to specify which link needs to be preloaded.
$books = App\Book::with('author')->get();foreach ($books as $book) { echo $book->author->name;}
For this operation, the following two SQL statements are executed:
select * from booksselect * from authors where id in (1, 2, 3, 4, 5, ...)
Preload multiple links
$books = App\Book::with('author', 'publisher')->get();
Nested pre-loading
$books = App\Book::with('author.contacts')->get();
Constrained preload
$users = App\User::with(['posts' => function ($query) { $query->where('title', 'like', '%first%');}])->get();$users = App\User::with(['posts' => function ($query) { $query->orderBy('created_at', 'desc');}])->get();
Delayed pre-loading #
Sometimes, after the upper-level model has been retrieved, the associated data may need to be preloaded. you can use the load method.
$books = App\Book::all();if ($someCondition) { $books->load('author', 'publisher');}$books->load(['author' => function ($query) { $query->orderBy('published_date', 'asc');}]);
Join model insert save method
Save a single Associated model
$comment = new App\Comment(['message' => 'A new comment.']);$post = App\Post::find(1);$post->comments()->save($comment);
Save multiple associated models
$post = App\Post::find(1); $post->comments()->saveMany([ new App\Comment(['message' => 'A new comment.']), new App\Comment(['message' => 'Another comment.']),]);
Save method and multiple-to-many Association
For multi-to-multi-join, you can specify attributes in the join table for the second parameter of save.
App\User::find(1)->roles()->save($role, ['expires' => $expires]);
The above code updates the expires field of the intermediate table.
Create method
The difference between the create method and the save method is that it uses arrays to create an associated model.
$post = App\Post::find(1);$comment = $post->comments()->create([ 'message' => 'A new comment.',]);
Update the "Belongs To" relationship
You can use the associate method when updating the belonsto relationship. this method sets the foreign key of the submodel.
$account = App\Account::find(10);$user->account()->associate($account);$user->save();
Use the dissociate method to remove the belonsto relationship.
$user->account()->dissociate();$user->save();
Rollback to rollback relationship
Intermediate table query condition #
You can usewherePivot
,wherePivotIn
,orWherePivot
,orWherePivotIn
Add query conditions.
$enterprise->with(['favorites' => function($query) { $query->wherePivot('enterprise_id', '=', 12)->select('id');}]);
Attaching/Detaching #
$ User = App \ User: find (1); // add a role $ user-> roles ()-> attach ($ roleId) for the user ); // add a role to the user and update the expires field $ user-> roles ()-> attach ($ roleId, ['expires' => $ expires]) of the intermediate table; // remove a single user role $ user-> roles ()-> detach ($ roleId); // remove all roles of a user $ user-> roles () -> detach ();
The attach and detach methods support array parameters and add and remove multiple
$user = App\User::find(1);$user->roles()->detach([1, 2, 3]);$user->roles()->attach([1 => ['expires' => $expires], 2, 3]);
Update the intermediate table (joined table) field
Use updateexisting to update the intermediate table
$user = App\User::find(1);$user->roles()->updateExistingPivot($roleId, $attributes);
Synchronize an intermediate table (synchronous Association )#
Using the sync method, you can specify that only the specified associations exist between two models.
$user->roles()->sync([1, 2, 3]);$user->roles()->sync([1 => ['expires' => true], 2, 3]);
Both of the preceding methods allow the user to have only one or two or three roles. if the user has another role, the user will be deleted.
Update the timestamp of the parent model #
Assuming that the scenario is as follows, we add a new comment to a post. we hope that the update time of the post will change accordingly. this behavior is very easy to implement in Eloquent.
Use the $ touches attribute in the submodel to implement this function.
belongsTo('App\Post'); }}
Now, when the comment is updated, the updated_at field of the post will also be updated.
$comment = App\Comment::find(1);$comment->text = 'Edit to this comment!';$comment->save();
The above is a detailed description of the Laravel framework-EloquentORM advanced section. For more information, see other related articles in the first PHP community!