[Laravel 5.2 Documentation] Eloquent ORM--association relationship

Source: Internet
Author: User

1. Introduction

Data tables are often associated with other tables, such as a blog post that may have many comments, or an order that is linked to a single user, eloquent makes it easy to organize and process these relationships, and supports many different types of affinity relationships:

    • One
    • One-to-many
    • Many-to-many
    • Far layer one to many
    • Polymorphic Correlation
    • Many-to-many polymorphic associations

2. Define Association relationships

Eloquent association relationships are defined in the form of eloquent model class methods. Like the eloquent model itself, correlation is also a powerful query builder, which defines correlation as a function that provides a powerful method chain and query capability. For example:

$user->posts ()->where (' active ', 1)->get ();

But before we dive into the relationship, let's first learn how to define each type of association:

One

One to one correlation is a very simple association, for example, a user model has a corresponding phone model. To define this model, we need to place the phone method in the user model, and the phone method should return the result of the Hasone method on the base class of the eloquent model:

 
  HasOne (' App\phone ');}    }

The first parameter passed to the Hasone method is the name of the associated model, and when the association relationship is defined, we can use the dynamic properties of eloquent to get the associated record. Dynamic properties allow us to access associative functions as if they were properties defined on the model:

$phone = User::find (1)->phone;

Eloquent the foreign key of the default association relationship is based on the model name, in this case, the phone model has a USER_ID foreign key by default, and if you want to override this convention, you can pass the second argument to the Hasone method:

return $this->hasone (' App\phone ', ' Foreign_key ');

In addition, eloquent assumes that the foreign key should have a matching ID on the parent, in other words, eloquent will go to the phone table with the ID value of the user table to query the phone record that matches the user_id. If you want to associate a relationship with a different value instead of an ID, you can pass the third argument to Hasone to specify a custom primary key:

return $this->hasone (' App\phone ', ' foreign_key ', ' Local_key ');

To define relative associations

We can access the phone model from User, and we can also define the correlation relationship in the phone model so that we can have the user of the phone. We can use the Belongsto method to define the association relative to the Hasone association:

 
  Belongsto (' App\user ');}    }

In the example above, eloquent will try to find the matching record by using the phone model's user_id to the user model. Eloquent generates the default foreign key name by associating the relationship method name with the _id suffix appended to the method name. However, if the foreign key on the phone model is not user_id, you can also pass the custom key name as a second parameter to the Belongsto method:

/** * Get the user */public function of the cell phone () {    return $this->belongsto (' App\user ', ' Foreign_key ');}

If the parent model does not use an ID as the primary key, or if you want to use a different column to connect to the child model, you can pass the parent table custom key as the third parameter to the Belongsto method:

/** * Get the corresponding user */public function of the phone () {    return $this->belongsto (' App\user ', ' foreign_key ', ' Other_key ');}

One-to-many

One-to-many is an association that defines a single model that has multiple other models. For example, a blog post has numerous comments, like other relationships, a one-to-many association is defined by defining a method in the eloquent model:

 
  Hasmany (' app\comment ');}    }

Remember, eloquent automatically determines the foreign key of the comment model, and for convenience, eloquent adds the owner model name plus the ID suffix as the foreign key. Therefore, in this example, eloquent assumes that the foreign key on the comment model is post_id.

Once the correlation relationship is defined, we can access the comment collection by accessing the Comments property. Keep in mind that because eloquent provides "dynamic properties", we can access the associated method just like the properties of the model:

$comments = App\post::find (1)->comments;foreach ($comments as $comment) {    //}

Of course, since all associations are also query builders, we can add more conditional constraints to the comments obtained by calling the comments method:

$comments = App\post::find (1)->comments ()->where (' title ', ' foo ')->first ();

As with the Hasone method, you can also reset the foreign key and local primary key by passing the extra parameter to the Hasmany method:

return $this->hasmany (' app\comment ', ' Foreign_key '); return $this->hasmany (' app\comment ', ' foreign_key ', ' Local_key ');

To define relative associations

Now that we have access to all the comments in the article, let's define an association relationship that allows you to access the article by commenting. To define a relative relationship with Hasmany, you need to define an association method in the sub-model to invoke the Belongsto method:

 
  Belongsto (' App\post ');}    }

After the correlation relationship is defined, we can get a comment corresponding post by accessing the dynamic property post:

$comment = App\comment::find (1); Echo $comment->post->title;

In the above example, eloquent attempts to match the id,eloquent of the post_id and post model of the comment model by using the associated method name plus the _id suffix to generate the default foreign key, and of course, you can also pass the custom foreign key name as the second argument to the Belongsto method, if your foreign key is not post_id, or if you want to customize it:

/** * Get comments corresponding to the blog post */public function post () {    return $this->belongsto (' app\post ', ' Foreign_key ');}

If your parent model does not use an ID as the primary key, or if you want to connect to the child model through other columns, you can pass the custom key name as the third parameter to the Belongsto method:

/** * Get comments corresponding to the blog post */public function post () {    return $this->belongsto (' app\post ', ' foreign_key ', ' Other_key ');}

Many-to-many

Many-to-many relationships are a little more complicated than hasone and hasmany associations. An example of this association relationship is that 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_user tables are named alphabetically by the associated model name and contain two columns for user_id and role_id.

Many-to-many associations are defined by writing a function that invokes the Belongstomany method on the eloquent base class:

 
  Belongstomany (' App\role ');}    }

Once an association relationship is defined, you can use dynamic property roles to access the user's role:

$user = App\user::find (1); foreach ($user->roles as $role) {    //}

Of course, as with all other relational types, you can call the roles method to add a conditional constraint to the associated query:

$roles = App\user::find (1)->roles ()->orderby (' name ')->get ();

As mentioned earlier, in order to determine the table name of the Association connection table, eloquent joins the names of the two associated models in alphabetical order. However, you can override this convention by passing the second argument to the Belongstomany method:

return $this->belongstomany (' app\role ', ' user_roles ');

In addition to the table name of the custom join table, you can also customize the column names of the fields in the table by passing extra parameters to the Belongstomany method. The third parameter is the foreign key name of the relationship model you define, and the fourth parameter is the foreign key name of the model you want to connect to:

return $this->belongstomany (' app\role ', ' user_roles ', ' user_id ', ' role_id ');

To define relative relationships

To define an association relationship relative to many-to-many associations, simply call the Belongstomany method in the correlation model. Let's define the users method in the role model:

 
  Belongstomany (' App\user ');}    }

As you can see, the associated relationship of the definition is exactly the same as defined in its corresponding User, except that the former refers to App\role, which references App\user, because we re-use the Belongstomany method, All of the common table and key customization options are available when defining association relationships with many-to-many counterparts.

Gets the columns of the intermediate table

As you've learned, dealing with many-to-many associations requires an intermediate table. Eloquent provides some useful ways to interact with it, for example, we assume that the user object has a lot of role objects associated with it, and after accessing these relationships, we can use the Pivot property on the model to access the intermediate table:

$user = App\user::find (1), foreach ($user->roles as $role) {    echo $role->pivot->created_at;}

Note that each role model that we get is automatically assigned the pivot attribute. This property contains a model that represents an intermediate table and can be used like any other eloquent model.

By default, only model keys can be used on Privot objects, and if your Privot table contains additional attributes, you must specify them when you define an association relationship:

return $this->belongstomany (' App\role ')->withpivot (' Column1 ', ' column2 ');

If you want your Privot table to automatically contain created_at and updated_at timestamps, use the Withtimestamps method when associating the relationship definition:

return $this->belongstomany (' App\role ')->withtimestamps ();

One-to-many on the far floor

The "one-to-many" association provides a convenient way to access the relationship between the distant layers through an intermediate association. For example, the country model might have multiple post models through the middle user model. In this example, you can easily aggregate all the articles in a given country, and let's look at what tables are needed to define this association relationship:

Countries    Id-integer    name-stringusers    id-integer    country_id-integer    name-stringposts    Id-integer    User_id-integer    title-string

Although the posts table does not contain country_id columns, the Hasmanythrough association provides access to all articles in a country through the $country->posts. To execute the query, eloquent checks the country_id on the intermediate table $users, finds the matching user ID, and queries the posts table with the user ID.

Now that we have looked at the data table structure of the association, let's define it on the country model:

 
  Hasmanythrough (' App\post ', ' App\user ');}    }

The first parameter passed to the Hasmanythrough method is the name of the model that we want to access eventually, and the second parameter is the middle model name.

The eloquent foreign key rule is usually used when executing this association query, and if you want to customize the foreign key of the association, you can pass them as the third and fourth arguments to the Hasmanythrough method. The third parameter is the foreign key name of the intermediate model, and the fourth parameter is the foreign key name of the final model.

Class Country extends model{public    function posts ()    {        return $this->hasmanythrough (' app\post ', ' app\ User ', ' country_id ', ' user_id ');}    }

Polymorphic Correlation

Table structure

Polymorphic associations allow a model to belong to multiple different models under a single association. For example, if an app user can like an article and likes a comment, use a polymorphic association, you can use a single likes table in both scenarios, first, let's look at the table structure needed to build this association:

Posts    id-integer    title-string    body-textcomments    id-integer    post_id-integer    Body-textli Kes    id-integer    likeable_id-integer    likeable_type-string

Two important columns to note are the likeable_id and likeable_type on the likes table. The likeable_id column corresponds to the ID value of post or comment, and the Imageable_type column corresponds to the class name of the owning model. When accessing the likeable association, ORM determines the type of the owning model and returns the corresponding model instance according to the Likeable_type column.

Model structure

Next, let's look at what we need to define in the model to build this association relationship:

 
  Morphto ();    }} Class Post extends model{    /**     * Get all the likes of this article     *    /Public Function likes ()    {        return $this Morphmany (' app\like ', ' likeable ');}    } Class Comment extends model{    /**     * Get the comment all points like     *    /Public Function likes ()    {        return $ This->morphmany (' app\like ', ' likeable ');}    }

Get polymorphic Associations

After the data tables and models are defined, you can access the association relationships through the model. For example, to access all the points of an article like, you can likes by using dynamic properties:

$post = App\post::find (1); foreach ($post->likes as $like) {    //}

You can also get the owning object of the Polymorphic association from the polymorphic model by calling the Morphto method. In this case, it is the likeable method in the like model. Therefore, we can access the method with dynamic properties:

$like = App\like::find (1); $likeable = $like->likeable;

The likeable association of the like model returns a post or comment instance, depending on which type of model owns that point.

Many-to-many polymorphic associations

Table structure

In addition to traditional polymorphic associations, you can define "many-to-many" polymorphic associations, for example, a post and video model for a blog may share a polymorphic association of a tag model. Using polymorphic associations with multiple pairs allows you to have a unique list of tags between blog posts and videos. First, let's look at the table structure:

Posts    id-integer    name-stringvideos    id-integer    name-stringtags    id-integer    Name-stringta Ggables    tag_id-integer    taggable_id-integer    taggable_type-string

Model structure

Next, we're going to define the correlation in the model. Both the post and video models have a tags method that calls the Morphtomany method of the eloquent base class:

 
  Morphtomany (' App\tag ', ' taggable ');}    }

To define relative relationships

Next, in the tag model, you should define a method for each association model, for example, we define a posts method and a videos method:

 
  Morphedbymany (' App\post ', ' taggable ');    }    /**     * Gets all videos assigned to this label */public    function videos ()    {        return $this->morphedbymany (' App\video ', ' Taggable ');}    }

Get Association Relationship

After you have defined the database and model, you can access the association relationship through the model. For example, to access all the tags of an article, you can use dynamic properties tags:

$post = App\post::find (1); foreach ($post->tags as $tag) {    //}

You can also get the owning object of a polymorphic association from the polymorphic model by accessing the method name called Morphedbymany. In this case, the posts or videos method in the tag model is:

$tag = App\tag::find (1); foreach ($tag->videos as $video) {    //}

3. Related Queries

Since all eloquent relationships are defined by functions, you can call these methods to get an instance of the associated relationship without having to manually execute the associated query. In addition, all eloquent association types are also query builders, allowing you to continue to add conditional constraints to the associated query before you finally execute SQL on the database.

For example, suppose that a User model has many related Post models in a blog system:

 
  Hasmany (' App\post ');}    }

You can query the posts association like this and add additional conditional constraints to that affinity relationship:

$user = App\user::find (1), $user->posts ()->where (' active ', 1)->get ();

You can use any Query builder on an association relationship!

Correlation Relation Method VS dynamic property

If you do not need to add additional conditional constraints to the eloquent associated query, you can simply access the associated object via dynamic properties, for example, or take the user and post model as an example, you can access all users ' articles like this:

$user = App\user::find (1); foreach ($user->posts as $post) {    //}

Dynamic properties are lazy loading, which means that the associated data is loaded when you actually access them. Because of this, developers often use eager loading to preload the associations that they know are to be accessed when the model is loaded. Craving loading effectively reduces the SQL queries that must be taken to load the Model association.

Querying an existing association relationship

When you access a record of a model, you may want to limit the number of query results based on the presence of an association relationship. For example, suppose you want to get all the blog posts with at least one comment, to implement this, you can pass the name of the associated relationship to the has method:

Get all articles with at least one comment ... $posts = App\post::has (' comments ')->get ();

You can also specify the operator and size to customize the query:

Get all articles with at least three reviews ... $posts = Post::has (' comments ', ' >= ', 3)->get ();

You can also use the "." To construct a nested has statement, for example, you want to get all the articles that have at least one comment and vote:

Get all articles with at least one comment to get voted ... $posts = Post::has (' comments.votes ')->get ();

If you need more powerful features, you can use the Wherehas and Orwherehas methods to place the where condition on the has query, which allows you to add a custom condition constraint to an association relationship condition constraint, such as checking the contents of a comment:

Get all articles with at least one comment containing foo words $posts = Post::wherehas (' Comments ', function ($query) {    $query->where (' content ', ' Like ', ' foo% ');}) ->get ();

Craving loading

When accessing database associations by property, the relational data is "lazy-loaded", which means that the associated relational data is not loaded until the first time it is accessed. However, eloquent can "crave load" affinity relationships while querying the parent model. Eager loading alleviates the n+1 query problem, to clarify the n+1 query problem, consider the book model associated to author:

 
  Belongsto (' App\author ');}    }

Now, let's get all the books and their authors:

$books = App\book::all (); foreach ($books as $book) {    echo $book->author->name;}

The loop first executes 1 queries to get all the books in the table, and then another query gets the author of each book, so if there are 25 books to do 26 queries: 1 times is to get the book itself, the remaining 25 queries are for each book to get its author.

Thankfully, we can use a craving load to reduce this operation to 2 queries. When querying, you can use the With method to specify an association relationship that should be loaded with a craving:

$books = App\book::with (' author ')->get (), foreach ($books as $book) {    echo $book->author->name;}

In this operation, only two queries are executed:

SELECT * FROM Booksselect * FROM authors where ID in (1, 2, 3, 4, 5, ...)

Craving to load multiple affinity relationships

Sometimes you need to be eager to load several different relationships in a single operation. To do this, you only need to add additional parameters to the With method:

$books = App\book::with (' Author ', ' publisher ')->get ();

Nested craving loading

To crave a nested association relationship, you can use the "." Grammar. For example, let's crave the personal contact of all authors and authors of all books in a eloquent statement:

$books = App\book::with (' author.contacts ')->get ();

Craving for load with conditional constraints

Sometimes we want a craving to load an affinity relationship, but we also want to specify more query criteria for the craving load:

$users = App\user::with ([' posts ' = function ($query) {    $query->where (' title ', ' Like ', '%first% ');}]) ->get ();

In this example, eloquent only wants to load the title containing first article. Of course, you can call other query builders to customize the craving load operation:

$users = App\user::with ([' posts ' = function ($query) {    $query->orderby (' created_at ', ' desc ');}]) ->get ();

Lazy Craving load

Sometimes you need to load an affinity relationship after the parent model has been acquired. This can be useful, for example, when you need to dynamically decide whether to load an association model:

$books = App\book::all (), if ($someCondition) {    $books->load (' Author ', ' publisher ');}

If you need to set more query conditions on a craving-loaded query, you can pass a closure to the Load method:

$books->load ([' Author ' = function ($query) {    $query->orderby (' published_date ', ' ASC ');}]);

4. Inserting the correlation model

Basic use

Save method

Eloquent provides a convenient way to add new models to an affinity relationship. For example, perhaps you need to insert a new comment to post model, you can insert comment directly from the Save method of the associated relationship instead of manually setting the Post_id property of comment:

$comment = new App\comment ([' message ' = ' A new comment. ']); $post = App\post::find (1); $post->comments ()->save ($comment);

Note that instead of accessing comments with dynamic properties, we call the comments method to get an instance of the association relationship. The Save method automatically adds the POST_ID value to the new comment model.

If you need to save multiple association models, you can use the Savemany method:

$post = App\post::find (1); $post->comments ()->savemany ([    New App\comment ([' message ' = ' A new Comment. ']) ,    new App\comment ([' message ' = ' another Comment. ']);

Save & Many-to-many associations

When dealing with many-to-many associations, the Save method receives an additional intermediate table attribute as an array as the second parameter:

App\user::find (1)->roles ()->save ($role, [' Expires ' = ' + $expires]);

Create method

In addition to the Save and Savemany methods, you can use the Create method, which receives an array of attributes, creates a model, and then inserts a database. The difference between save and create is that save receives the entire eloquent model instance and the create receives the native PHP array:

$post = App\post::find (1); $comment = $post->comments ()->create ([    ' message ' = ' A new comment. ',] ');

Before using the Create method, make sure to browse the properties batch assignment document.

Update "belongs to" Association

When updating a Belongsto association, you can use the Associate method, which sets the foreign key in the child model:

$account = App\account::find, $user->account ()->associate ($account), $user->save ();

When removing belongsto associations, you can use the dissociate method. This method cancels the foreign key and association on the sub-model:

$user->account ()->dissociate (); $user->save ();

Many-to-many associations

Attach/Detach

When dealing with many-to-many associations, eloquent provides some additional helper functions to make it easier to process the associated model. For example, let's assume that a user may have multiple roles and one role belongs to multiple users, and you can use the Attach method to insert a record attach role to a user by inserting it in the intermediate table of the connection model:

$user = App\user::find (1); $user->roles ()->attach ($roleId);

Additional associations are related to the model, and additional inserted data can be passed in an array form to the intermediate table:

$user->roles ()->attach ($roleId, [' Expires ' + $expires]);

Of course, it is sometimes necessary to remove a role from a user, to remove a many-to-many association record, and to use the detach method. The detach method will remove the corresponding record from the intermediate table, however, the two models remain unchanged in the database:

Remove a role from a specified user ... $user->roles ()->detach ($roleId);//Remove all roles from the specified user ... $user->roles ()->detach ();

For convenience, attach and detach also receive an array form of ID as input:

$user = App\user::find (1); $user->roles ()->detach ([1, 2, 3]); $user->roles ()->attach ([1 = [' Expires ' = > $expires], 2, 3]);

Synchronous

You can also use the Sync method to build many-to-many associations. The sync method receives an array form ID and places it in the intermediate table. Any IDs that are not in the array will be removed from the intermediate table. Therefore, after the operation is complete, only the ID corresponding record in the array also exists in the intermediate table:

$user->roles ()->sync ([1, 2, 3]);

You can also pass additional intermediate table values along with the ID:

$user->roles ()->sync ([1 = [' Expires ' = True], 2, 3]);

Trigger parent Timestamp

When a model belongs to another, such as comment belongs to Post, the time stamp of the parent model is also updated when the sub-model is updated, for example, when the comment model is updated, you may want to "trigger" the updated_at timestamp to create the post of the model to which it belongs. Eloquent makes this simple, just add the touches attribute containing the name of the associated relationship to the child model:

 
  Belongsto (' App\post ');}    }

Now, when you update comment, the owning model post will also update its UPDATED_AT value:

$comment = App\comment::find (1); $comment->text = ' Edit to this comment! '; $comment->save ();
  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.