Laravel notes-eloquent ORM (associated relationship)

Source: Internet
Author: User
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 ();

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.