This post is from the professional Laravel developer community, original link: learnku.com/laravel/t/3…

Defining model associations in Laravel is something every Laravel developer has probably done more than once. However, you may encounter various problems when trying to implement associations. Because Laravel has all kinds of connections, which one should you choose? When it comes to querying models, how can we leverage the power of model association?

Laravel’s model correlation can be confusing. If you don’t fully understand how Laravel’s correlation works at this point, don’t worry, you’ll understand it better after reading this article.

Which model association should we use?

To answer this question, you first need to know what the options are available. Laravel has three different types of associations.

  • One to one
  • More than a pair of
  • Many to many

We’ll explore the different association types one by one and explain when they should be used.

One to one

One-to-one association is the most basic association that exists today. This association means that model A can only link to model B, and vice versa. For example, a User model and a Passport model become one-to-one associations. A user can have only one pass, and a pass belongs to only one user.

Let’s look at how to define this association in code.

<? php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { publicfunction passport() {
        return $this->hasOne(App\Passport::class); }}Copy the code

In the User model we create a Passport method. We use the hasOne method to tell Laravel that the User model has a Passport.

Note: All methods used to define associations have optional additional parameters in which you can define local and foreign keys. By default, Laravel will assume that you defined passport_id in the user model because you are trying to create an association with the Passport model. Keep this in mind when creating migration files!

In the Passport model, we need to define the inverse association. We want the Passport model to know that it belongs to the User model. We can do this using the belongsTo method.

<? php namespace App; use Illuminate\Database\Eloquent\Model; class Passport extends Model { publicfunction user() {
        return $this->belongsTo(App\User::class); }}Copy the code

More than a pair of

The next association you can define in Laravel is a one-to-many association. This type association means that A model of type A can be linked to multiple models of type B. But A model of type B belongs only to A model of type A.

For example, the association between the User model and the Invoice model is a one-to-many association. A user can have multiple bills, but the bills belong to only one user.

In the code it looks like this:

<? php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { publicfunction invoices() {
        return $this->hasMany(App\Invoice::class); }}Copy the code

It looks just like the code we used to define one-to-one associations, right?

All we need to do now is let the Invoice model know that it belongs to the User model. Let’s define the inverse correspondence relation of a one-to-many relation.

<? php namespace App; use Illuminate\Database\Eloquent\Model; class Invoice extends Model { publicfunction user() {
        return $this->belongsTo(App\User::class); }}Copy the code

Many to many

The last association to be defined is a many-to-many association. This type association means that A model of type A can be linked to multiple models of type B and vice versa.

For example, the association between the Invoice model and the Product model will be a many-to-many association. Bills can contain multiple products, and products can belong to multiple bills.

<? php namespace App; use Illuminate\Database\Eloquent\Model; class Invoice extends Model { publicfunction products() {
        return $this->belongsToMany(App\Product::class); }}Copy the code

You can define the inverse of the association like this:

<? php namespace App; use Illuminate\Database\Eloquent\Model; class Product extends Model { publicfunction invoices() {
        return $this->belongsToMany(App\Invoice::class); }}Copy the code

Many-to-many associations are slightly more difficult to implement because they require intermediate tables in the database. You can create this intermediate table in Laravel by creating a migration file.

The remote connection

Remote one-to-one

The has One through association is implemented through a single intermediate association model. If each vendor has a user and each user is associated with a user history, then the vendor can access the user’s history through the user.

Here is the database table needed to define this association:

suppliers:
- idproducts:
- id
- supplier_idproduct_history:
- id
- product_id
Copy the code

Even if the PRODUCt_History table does not contain the supplier_ID column, a vendor can access the Product_History record by using the “has one through” relationship.

<? php namespace App; use Illuminate\Database\Eloquent\Model; class Supplier extends Model { publicfunction productHistory() {
        return $this->hasOneThrough(App\History::class, App\Product::class); }}Copy the code

The first parameter passed to the hasOneThrough method is the name of the model you want to access. The second parameter is the name of the intermediate model.

Remote one-to-many

The “Has many through” association is equivalent to the “has One Through” association, only for multiple records. Let’s use the previous example, but let’s change one thing: products can now have multiple history entries instead of one. The database table remains unchanged.

<? php namespace App; use Illuminate\Database\Eloquent\Model; class Supplier extends Model { publicfunction productHistory() {
        return $this->hasManyThrough(App\History::class, App\Product::class); }}Copy the code

In this way, the vendor model can access the product’s history entry.

Query related

Querying an association is very simple. Because we defined a one-to-one association for Passport and a one-to-many association for Invoice, we can use them in the User model. On each instance of the User model, we get the corresponding Passport and Invoice.

<? php$user= \App\User::find(1); // Query the passport association$user->passport->expiration_date; // query the invoice associated with foreach($user->invoices as $invoice) {
    $invoice->total_amount;
}
Copy the code

You can also query the reverse association of an association. If you have a bill, you can get the user for that bill.

<? php$invoice = \App\Invoice::find(1);
// Get the user
$invoice->user->first_name;
Copy the code

Querying a many-to-many association works exactly like any other association. In addition, a many-to-many association has a pivot attribute. This property represents an intermediate table and can be used just like any other model.

For example, if the joined table has a CREATED_AT field, we can use Pivot to retrieve the CREATED_AT field.

<? php$invoice= \App\Invoice::find(1); // get product 'created_at' foreach($invoice->products as $product) {
    $product->pivot->created_at;
}
Copy the code

Queries for Has One Through and Has many Through work in exactly the same way as other associations.

Adding constraints

You can add constraints to relationships at query time. Take a look at the following example:

<? php$user->passport()->where('active', 1)->orderBy('expiration_date');
Copy the code

Check whether the association exists

Sometimes you want to check to see if there are any associations added to the model. Laravel has a few methods that you can use to check:

<? PHP // find all users with passports$users = App\User::has('passport')->get(); // Find all users without passports$users = App\User::doesntHave('passport')->get(); // Find the invoice with 5 or more products$invoices = App\Invoice::has('products'.'> =', 5)->get();
Copy the code

Hopefully this article will give you a better understanding of Laravel’s model correlation. Thanks for reading!