모델 협회
ㅋㅋ +
Eloquent: 연관
- 소개
- 데이터베이스 테이블 일반적으로 서로 관련이 있습니다. 예를 들어, 블로그 게시물에 댓글이 많을 수도 있고, 주문이 주문한 사용자에 해당할 수도 있습니다. Eloquent는 이러한 연관을 쉽게 관리하고 사용할 수 있으며 다양한 유형의 연관을 지원합니다:
- One-to-one
- One-to-many
- Many-to-many
- 원격 일대일
- 원격 일대다
- 일대일(다형성 연관)
- 일대다(다형성 연관)
Define Associations
Eloquent 연관은 Eloquent 모델 클래스의 메서드로 제공됩니다. Eloquent 모델 자체와 마찬가지로 연관은 강력한 체인 호출 및 쿼리 기능을 제공하는 강력한 쿼리 문 작성기로 사용될 수도 있습니다. 예를 들어 posts
연결에 대한 호출 체인에 제약 조건을 연결할 수 있습니다. posts
关联的链式调用中附加一个约束条件:
$user->posts()->where('active', 1)->get();
不过在深入使用关联之前,让我们先学习如何定义每种关联类型。
一对一
一对一是最基本的关联关系。例如,一个 User
模型可能关联一个 Phone
模型。为了定义这个关联,我们要在 User
模型中写一个 phone
方法。在 phone
方法内部调用 hasOne
方法并返回其结果:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model{ /** * Get the phone record associated with the user. */ public function phone() { return $this->hasOne('App\Phone'); } }
hasOne
方法的第一个参数是关联模型的类名。一旦定义了模型关联,我们就可以使用 Eloquent 动态属性获得相关的记录。动态属性允许你访问关系方法就像访问模型中定义的属性一样:
$phone = User::find(1)->phone;
Eloquent 会基于模型名决定外键名称。在这种情况下,会自动假设 Phone
模型有一个 user_id
外键。如果你想覆盖这个约定,可以传递第二个参数给 hasOne
方法:
return $this->hasOne('App\Phone', 'foreign_key');
另外,Eloquent 假设外键的值是与父级 id (或自定义 $primaryKey) 列的值相匹配的。换句话说,Eloquent 将会在 Phone 记录的 user_id 列中查找与用户表的 id 列相匹配的值。如果您希望该关联使用 id 以外的自定义键名,则可以给 hasOne 方法传递第三个参数:
return $this->hasOne('App\Phone', 'foreign_key', 'local_key');
定义反向关联
我们已经能从 User
模型访问到 Phone
模型了。现在,让我们再在 Phone
模型上定义一个关联,这个关联能让我们访问到拥有该电话的 User
模型。我们可以使用与 hasOne
方法对应的 belongsTo
方法来定义反向关联:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Phone extends Model{ /** * 获得拥有此电话的用户 */ public function user() { return $this->belongsTo('App\User'); } }
在上面的例子中, Eloquent 会尝试匹配 Phone
模型上的 user_id
至 User
模型上的 id
。它是通过检查关系方法的名称并使用 _id
作为后缀名来确定默认外键名称的。但是,如果 Phone
模型的外键不是 user_id
,那么可以将自定义键名作为第二个参数传递给 belongsTo
方法:
/** * 获得拥有此电话的用户 */ public function user(){ return $this->belongsTo('App\User', 'foreign_key'); }
如果父级模型没有使用 id
作为主键,或者是希望用不同的字段来连接子级模型,则可以通过给 belongsTo
/** * 获得拥有此电话的用户 */ public function user(){ return $this->belongsTo('App\User', 'foreign_key', 'other_key'); }하지만 연결 사용에 대해 자세히 알아보기 전에 각 연결 유형을 정의하는 방법을 알아보겠습니다.
일대일
User
모델은 Phone
모델과 연결될 수 있습니다. 이 연결을 정의하려면 User
모델에 phone
메서드를 작성해야 합니다. phone
메서드 내에서 hasOne
메서드를 호출하고 결과를 반환합니다. 🎜<?php namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model{ /** * 获取博客文章的评论 */ public function comments() { return $this->hasMany('App\Comment'); } }🎜
hasOne
메서드의 첫 번째 매개변수는 해당 클래스의 클래스 이름입니다. 관련 모델. 모델 연관이 정의되면 Eloquent 동적 속성을 사용하여 관련 레코드를 얻을 수 있습니다. 동적 속성을 사용하면 모델에 정의된 속성과 마찬가지로 관계형 메서드에 액세스할 수 있습니다. 🎜$comments = App\Post::find(1)->comments;foreach ($comments as $comment) { //}🎜Eloquent는 모델 이름을 기반으로 외래 키 이름을 결정합니다. 이 경우
Phone
모델에 user_id
외래 키가 있다고 자동으로 가정됩니다. 이 규칙을 무시하려면 hasOne
메소드에 두 번째 매개변수를 전달할 수 있습니다: 🎜$comment = App\Post::find(1)->comments()->where('title', 'foo')->first();🎜 또한 Eloquent는 외래 키의 값이 상위 ID의 값과 동일하다고 가정합니다. (또는 사용자 정의 $primaryKey) 열 일치. 즉, Eloquent는 Users 테이블의 id 열과 일치하는 Phone 레코드의 user_id 열에서 값을 찾습니다. 연결에서 id가 아닌 사용자 정의 키 이름을 사용하도록 하려면 hasOne 메소드에 세 번째 매개변수를 전달할 수 있습니다: 🎜
return $this->hasMany('App\Comment', 'foreign_key'); return $this->hasMany('App\Comment', 'foreign_key', 'local_key');
역방향 연결 정의
🎜우리는 이미User
모델에서 Phone
모델에 접근할 수 있습니다. 이제 전화를 소유한 User
모델에 대한 액세스를 제공하는 Phone
모델에 또 다른 연결을 정의해 보겠습니다. hasOne
메소드에 해당하는 belongsTo
메소드를 사용하여 역방향 연관을 정의할 수 있습니다: 🎜<?php namespace App; use Illuminate\Database\Eloquent\Model; class Comment extends Model{ /** * 获取此评论所属文章 */ public function post() { return $this->belongsTo('App\Post'); } }🎜위의 예에서 Eloquent는
Phone
를 일치시키려고 시도합니다. 모델의 user_id
를 User
모델의 id
로 설정하세요. 관계 메서드의 이름을 검사하고 _id
를 이름 접미사로 사용하여 기본 외래 키 이름을 결정합니다. 그러나 Phone
모델의 외래 키가 user_id
가 아닌 경우 사용자 정의 키 이름이 belongsTo
의 두 번째 매개변수로 전달될 수 있습니다. 방법: 🎜 $comment = App\Comment::find(1); echo $comment->post->title;🎜상위 모델이 기본 키로
id
를 사용하지 않거나 다른 필드를 사용하여 하위 모델을 연결하려는 경우 세 번째 매개변수를 belongsTo에 전달할 수 있습니다.
메소드 상위 데이터 테이블의 사용자 정의 키를 🎜/** * 获取此评论所属文章 */ public function post(){ return $this->belongsTo('App\Post', 'foreign_key'); }🎜🎜🎜🎜🎜🎜 형식으로 지정합니다.
일대다
"일대다" 연관은 단일 모델이 임의 개수의 다른 연관된 모델을 갖도록 정의하는 데 사용됩니다. 예를 들어, 블로그 게시물에는 댓글 수가 무한할 수 있습니다. 다른 모든 Eloquent 관계와 마찬가지로 일대다 관계의 정의는 Eloquent 모델에 메소드를 작성하는 것입니다:
/** * 获取此评论所属文章 */ public function post(){ return $this->belongsTo('App\Post', 'foreign_key', 'other_key'); }
Eloquent가 Comment
모델의 외래 키 속성을 자동으로 결정한다는 점을 기억하세요. . 관례적으로 Eloquent는 모델 이름의 "snake case" 형식과 _id
접미사를 외래 키 필드로 사용합니다. 따라서 위의 예에서 Eloquent는 Post
모델에 해당하는 Comment
의 외래 키가 post_id
라고 가정합니다. Comment
模型的外键属性。按照约定,Eloquent 将会使用所属模型名称的 『snake case』形式,再加上 _id
后缀作为外键字段。因此,在上面这个例子中,Eloquent 将假定 Comment
对应到 Post
模型上的外键就是 post_id
。
一旦关系被定义好以后,就可以通过访问 Post
模型的 comments
属性来获取评论的集合。记住,由于 Eloquent 提供了『动态属性』 ,所以我们可以像访问模型的属性一样访问关联方法:
<?php namespace App; use Illuminate\Database\Eloquent\Model;class User extends Model{ /** * 用户拥有的角色 */ public function roles() { return $this->belongsToMany('App\Role'); } }
当然,由于所有的关联还可以作为查询语句构造器使用,因此你可以使用链式调用的方式,在 comments
方法上添加额外的约束条件:
$user = App\User::find(1); foreach ($user->roles as $role) { // }
正如 hasOne
方法一样,你也可以在使用 hasMany
方法的时候,通过传递额外参数来覆盖默认使用的外键与本地键:
$roles = App\User::find(1)->roles()->orderBy('name')->get();
一对多(反向)
现在,我们已经能获得一篇文章的所有评论,接着再定义一个通过评论获得所属文章的关联关系。这个关联是 hasMany
关联的反向关联,需要在子级模型中使用 belongsTo
方法定义它:
return $this->belongsToMany('App\Role', 'role_user');
这个关系定义好以后,我们就可以通过访问 Comment
模型的 post
这个『动态属性』来获取关联的 Post
模型了:
return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id');
在上面的例子中,Eloquent 会尝试用 Comment
模型的 post_id
与 Post
模型的 id
进行匹配。默认外键名是 Eloquent 依据关联名,并在关联名后加上 _ 再加上主键字段名作为后缀确定的。当然,如果 Comment
模型的外键不是 post_id
,那么可以将自定义键名作为第二个参数传递给 belongsTo
方法:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Role extends Model{ /** * 拥有此角色的用户。 */ public function users() { return $this->belongsToMany('App\User'); } }
如果父级模型没有使用 id
作为主键,或者是希望用不同的字段来连接子级模型,则可以通过给 belongsTo
Post
모델의 Comments
속성에 액세스하여 댓글 컬렉션을 얻을 수 있습니다. Eloquent는 "동적 속성"을 제공하므로 모델의 속성에 액세스하는 것처럼 관계 메서드에 액세스할 수 있습니다. $user = App\User::find(1); foreach ($user->roles as $role) { echo $role->pivot->created_at; }물론 모든 관계는 쿼리문 생성자로도 사용할 수 있으므로 체인 호출 방식을 사용할 수 있습니다.
comments
메서드에 대한 제약 조건: return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');
hasOne
메서드와 마찬가지로 hasMany
메서드도 사용할 수 있습니다. 추가 매개변수를 전달하여 외래 키 및 로컬 키: return $this->belongsToMany('App\Role')->withTimestamps();
hasMany
연관의 역 연관입니다. 하위 모델에서 이를 정의하려면 belongsTo
메소드를 사용해야 합니다. 🎜return $this->belongsToMany('App\Podcast') ->as('subscription') ->withTimestamps();🎜이 관계가 정의된 후 연관된
Post
모델을 얻기 위해 Comment
모델의 post
"동적 속성"을 통해 이에 접근할 수 있습니다: 🎜$users = User::with('podcasts')->get(); foreach ($users->flatMap->podcasts as $podcast) { echo $podcast->subscription->created_at; }🎜위의 예에서 Eloquent는 다음을 시도합니다.
Comment
모델의 post_id
를 사용하여 Post
모델의 id
와 일치시킵니다. 기본 외래 키 이름은 연결 이름에 따라 Eloquent에 의해 결정되며 그 뒤에는 _ 및 기본 키 필드 이름이 접미사로 붙습니다. 물론 Comment
모델의 외래 키가 post_id
가 아닌 경우 사용자 정의 키 이름을 belongsTo
의 두 번째 매개변수로 전달할 수 있습니다. 방법: 🎜 return $this->belongsToMany('App\Role')->wherePivot('approved', 1); return $this->belongsToMany('App\Role')->wherePivotIn('priority', [1, 2]);🎜상위 모델이 기본 키로
id
를 사용하지 않거나 다른 필드를 사용하여 하위 모델을 연결하려는 경우 세 번째 매개변수를 belongsTo에 전달할 수 있습니다.
메소드 상위 데이터 테이블의 사용자 정의 키를 🎜<?php namespace App; use Illuminate\Database\Eloquent\Model; class Role extends Model{ /** * 拥有此角色的所有用户 */ public function users() { return $this->belongsToMany('App\User')->using('App\UserRole'); } }🎜🎜🎜🎜🎜🎜 형식으로 지정합니다.
다대다
다대다 관계는 hasOne
및 hasMany
관계보다 약간 더 복잡합니다. 예를 들어, 사용자는 많은 역할을 가질 수 있으며 이러한 역할은 다른 사용자와 공유됩니다. 예를 들어, 많은 사용자가 "관리자" 역할을 가질 수 있습니다. 이 연결을 정의하려면 users
, roles
및 role_user
라는 세 개의 데이터베이스 테이블이 필요합니다. role_user
테이블은 연관된 두 모델의 알파벳순으로 이름이 지정되며 user_id
및 role_id
필드를 포함합니다. hasOne
和 hasMany
关联稍微复杂些。举个例子,一个用户可以拥有很多种角色,同时这些角色也被其他用户共享。例如,许多用户可能都有 「管理员」 这个角色。要定义这种关联,需要三个数据库表: users
,roles
和 role_user
。role_user
表的命名是由关联的两个模型按照字母顺序来的,并且包含了 user_id
和 role_id
字段。
多对多关联通过调用 belongsToMany
这个内部方法返回的结果来定义,例如,我们在 User
模型中定义 roles
方法:
<?php namespace App; use Illuminate\Database\Eloquent\Relations\Pivot; class UserRole extends Pivot{ // }
一旦关联关系被定义后,你可以通过 roles
动态属性获取用户角色:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Role extends Model{ /** * 拥有此角色的用户。 */ public function users() { return $this->belongsToMany('App\User') ->using('App\UserRole') ->withPivot([ 'created_by', 'updated_by' ]); } }
当然,像其它所有关联模型一样,你可以使用 roles
方法,利用链式调用对查询语句添加约束条件:
/** * 标识 ID 是否自增。 * * @var bool */ public $incrementing = true;
正如前面所提到的,为了确定关联连接表的表名,Eloquent 会按照字母顺序连接两个关联模型的名字。当然,你也可以不使用这种约定,传递第二个参数到 belongsToMany
方法即可:
suppliers id - integer users id - integer supplier_id - integer history id - integer user_id - integer
除了自定义连接表的表名,你还可以通过传递额外的参数到 belongsToMany
方法来定义该表中字段的键名。第三个参数是定义此关联的模型在连接表里的外键名,第四个参数是另一个模型在连接表里的外键名:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Supplier extends Model{ /** * 用户的历史记录。 */ public function userHistory() { return $this->hasOneThrough('App\History', 'App\User'); } }
定义反向关联
要定义多对多的反向关联, 你只需要在关联模型中调用 belongsToMany
方法。我们在 Role
模型中定义 users
方法:
class Supplier extends Model{ /** * 用户的历史记录。 */ public function userHistory() { return $this->hasOneThrough( 'App\History', 'App\User', 'supplier_id', // 用户表外键 'user_id', // 历史记录表外键 'id', // 供应商本地键 'id' // 用户本地键 ); } }
如你所见,除了引入模型为 AppUser
外,其它与在 User
模型中定义的完全一样。由于我们重用了 belongsToMany
belongsToMany
에 의해 반환된 결과를 호출하여 정의됩니다. 예를 들어 User<에 roles
메소드를 정의합니다. /code> 모델: countries
id - integer
name - string
users
id - integer
country_id - integer
name - string
posts
id - integer
user_id - integer
title - string
연결이 정의되면 roles
동적 속성을 통해 사용자 역할을 얻을 수 있습니다. 🎜<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Country extends Model{
/**
* 当前国家所有文章。
*/
public function posts()
{
return $this->hasManyThrough('App\Post', 'App\User');
}
}
🎜물론 다른 모든 연결 모델과 마찬가지로 를 사용할 수 있습니다. >roles
메소드, 체인 호출을 사용하여 쿼리 문에 제약 조건을 추가합니다: 🎜class Country extends Model{
public function posts()
{
return $this->hasManyThrough(
'App\Post',
'App\User',
'country_id', // 用户表外键
'user_id', // 文章表外键
'id', // 国家表本地键
'id' // 用户表本地键
);
}
}
🎜 앞서 언급했듯이 관련 연결 테이블의 테이블 이름을 결정하기 위해 Eloquent는 두 관련 모델의 이름을 다음과 같이 연결합니다. 알파벳 순서. 물론 이 규칙을 사용하지 않고 두 번째 매개변수를 belongsToMany
메서드에 전달할 수도 있습니다. 🎜posts
id - integer
name - string
users
id - integer
name - string
images
id - integer
url - string
imageable_id - integer
imageable_type - string
🎜연결 테이블의 테이블 이름을 사용자 정의하는 것 외에도 <에 추가 매개변수를 전달할 수도 있습니다. code>belongsToMany
메소드를 사용하여 테이블에 있는 필드의 키 이름을 정의합니다. 세 번째 매개변수는 연결 테이블에서 이 연관을 정의하는 모델의 외래 키 이름이고, 네 번째 매개변수는 연결 테이블에 있는 다른 모델의 외래 키 이름입니다. 🎜<?php namespace App; use Illuminate\Database\Eloquent\Model; class Image extends Model{ /** * 获取拥有此图片的模型。 */ public function imageable() { return $this->morphTo(); } } class Post extends Model{ /** * 获取文章图片。 */ public function image() { return $this->morphOne('App\Image', 'imageable'); } } class User extends Model{ /** * 获取用户图片。 */ public function image() { return $this->morphOne('App\Image', 'imageable'); } }
역연관 정의
🎜다대다 역연관을 정의하려면 연관 모델에서belongsToMany
메소드만 호출하면 됩니다. Role
모델에서 users
메소드를 정의합니다: 🎜$post = App\Post::find(1); $image = $post->image;🎜보시다시피
AppUser
모델 도입을 제외하고 다른 모든 것 와 동일합니다. >User
는 모델에 정의된 것과 정확히 동일합니다. belongsToMany
메서드를 재사용하므로 사용자 정의 조인 테이블 테이블 이름과 사용자 정의 조인 테이블에 있는 키의 필드 이름도 여기에 적용됩니다. 🎜🎜🎜중간 테이블 필드 가져오기
방금 배웠듯이, 다대다 관계는 지원을 제공하기 위해 중간 테이블이 필요합니다. Eloquent는 이 테이블과 상호 작용하는 몇 가지 유용한 방법을 제공합니다. 예를 들어 User
개체가 여러 Role
개체와 연결되어 있다고 가정해 보겠습니다. 이러한 연관된 객체를 얻은 후 모델의 pivot
속성을 사용하여 중간 테이블의 데이터에 액세스할 수 있습니다. User
对象关联了多个 Role
对象。在获得这些关联对象后,可以使用模型的 pivot
属性访问中间表的数据:
$image = App\Image::find(1); $imageable = $image->imageable;
需要注意的是,我们获取的每个 Role
模型对象,都会被自动赋予 pivot
属性,它代表中间表的一个模型对象,并且可以像其他的 Eloquent 模型一样使用。
默认情况下,pivot
对象只包含两个关联模型的主键,如果你的中间表里还有其他额外字段,你必须在定义关联时明确指出:
posts id - integer title - string body - text videos id - integer title - string url - string comments id - integer body - text commentable_id - integer commentable_type - string
如果你想让中间表自动维护 created_at
和 updated_at
时间戳,那么在定义关联时附加上 withTimestamps
方法即可:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Comment extends Model{ /** * 获取拥有此评论的模型。 */ public function commentable() { return $this->morphTo(); } } class Post extends Model{ /** * 获取此文章的所有评论。 */ public function comments() { return $this->morphMany('App\Comment', 'commentable'); } } class Video extends Model{ /** * 获取此视频的所有评论。 */ public function comments() { return $this->morphMany('App\Comment', 'commentable'); } }
自定义 pivot
属性名称
如前所述,来自中间表的属性可以使用 pivot
属性访问。但是,你可以自由定制此属性的名称,以便更好的反应其在应用中的用途。
例如,如果你的应用中包含可能订阅的用户,则用户与博客之间可能存在多对多的关系。如果是这种情况,你可能希望将中间表访问器命名为 subscription
取代 pivot
。这可以在定义关系时使用 as
方法完成:
$post = App\Post::find(1);foreach ($post->comments as $comment) { // }
一旦定义完成,你可以使用自定义名称访问中间表数据:
$comment = App\Comment::find(1); $commentable = $comment->commentable;
通过中间表过滤关系
在定义关系时,你还可以使用 wherePivot
和 wherePivotIn
方法来过滤 belongsToMany
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우리가 얻는 각
Role
모델 객체는 주목해야 합니다. 에는 중간 테이블의 모델 객체를 나타내며 다른 Eloquent 모델처럼 사용할 수 있는 pivot
속성이 자동으로 할당됩니다. 기본적으로 pivot
객체에는 두 관련 모델의 기본 키만 포함됩니다. 중간 테이블에 다른 추가 필드가 있는 경우 관계를 정의할 때 이를 명시적으로 표시해야 합니다.
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model{ /** * 获取文章的所有标签。 */ public function tags() { return $this->morphToMany('App\Tag', 'taggable'); } }중간 테이블이 자동으로
created_at
및 updated_at
타임스탬프를 유지하도록 하려면 연결을 정의할 때 withTimestamps
메서드를 추가하세요. <?php namespace App; use Illuminate\Database\Eloquent\Model; class Tag extends Model{ /** * 获取被打上此标签的所有文章。 */ public function posts() { return $this->morphedByMany('App\Post', 'taggable'); } /** * 获取被打上此标签的所有视频。 */ public function videos() { return $this->morphedByMany('App\Video', 'taggable'); } }🎜
피벗
속성 이름을 사용자 정의하세요🎜🎜앞서 언급했듯이 중간 테이블의 속성은 피벗<을 사용하여 액세스할 수 있습니다. /코드> 속성 . 그러나 애플리케이션에서의 용도를 더 잘 반영하기 위해 이 속성의 이름을 자유롭게 사용자 정의할 수 있습니다. 🎜🎜예를 들어 앱에 구독할 수 있는 사용자가 포함된 경우 사용자와 블로그 사이에 다대다 관계가 있을 수 있습니다. 이 경우 pivot
대신 중간 테이블 접근자 subscription
의 이름을 지정할 수 있습니다. 이는 관계를 정의할 때 as
메소드를 사용하여 수행할 수 있습니다: 🎜$post = App\Post::find(1);foreach ($post->tags as $tag) {
//
}
🎜정의되면 사용자 정의 이름을 사용하여 중간 테이블 데이터에 액세스할 수 있습니다: 🎜$tag = App\Tag::find(1);foreach ($tag->videos as $video) {
//
}
🎜🎜중간 테이블을 통해 관계 필터링🎜🎜관계를 정의할 때 wherePivot
및 wherePivotIn
메서드를 사용하여 belongsToMany
를 필터링할 수도 있습니다. 코드> 다음에 대한 결과 반환: 🎜use Illuminate\Database\Eloquent\Relations\Relation;
Relation::morphMap([
'posts' => 'App\Post',
'videos' => 'App\Video',
]);
🎜🎜🎜🎜🎜🎜중간 테이블 모델 정의
사용자 정의 중간 테이블 모델 정의
연관 관계에서 중간 테이블을 나타내는 사용자 정의 모델을 정의하려면 연관 정의 시 using
메서드를 호출하면 됩니다. . 사용자 정의 다대다
중간 테이블 모델은 IlluminateDatabaseEloquentRelationsPivot 클래스에서 확장되어야 하며 사용자 정의 다대다(다형성)
중간 테이블 모델은 IlluminateDatabaseEloquentRelationsMorphPivot 클래스를 상속해야 합니다. 예를 들어, using
方法。自定义多对多
中间表模型都必须扩展自 IlluminateDatabaseEloquentRelationsPivot 类,自定义多对多(多态)
中间表模型必须继承 IlluminateDatabaseEloquentRelationsMorphPivot 类。例如,
我们在写 Role 模型的关联时,使用自定义中间表模型 UserRole
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model{
/**
* 获取该用户的所有文章。
*/
public function posts()
{
return $this->hasMany('App\Post');
}
}
当定义 UserRole
模型时,我们要扩展 Pivot
类:
$user = App\User::find(1);
$user->posts()->where('active', 1)->get();
你可以组合使用 using
和 withPivot
从中间表来检索列。例如,通过将列名传递给 withPivot
方法,就可以从 UserRole
中间表中检索出 created_by
和 updated_by
两列数据。
$user = App\User::find(1);
foreach ($user->posts as $post) {
//
}
带有递增 ID 的自定义中继模型
如果你用一个自定义的中继模型定义了多对多的关系,而且这个中继模型拥有一个自增的主键,你应当确保这个自定义中继模型类中定义了一个 incrementing
属性其值为 true
:
// 获取至少存在一条评论的所有文章...
$posts = App\Post::has('comments')->get();
远程一对一关系
远程一对一关联通过一个中间关联模型实现。
例如,如果每个供应商都有一个用户,并且每个用户与一个用户历史记录相关联,那么供应商可以通过用户访问用户的历史记录,让我们看看定义这种关系所需的数据库表:
// 获取评论超过三条的文章...
$posts = App\Post::has('comments', '>=', 3)->get();
虽然 history
表不包含 supplier_id
,但 hasOneThrough
关系可以提供对用户历史记录的访问,以访问供应商模型。现在我们已经检查了关系的表结构,让我们在 Supplier
模型上定义相应的方法:
// 获取拥有至少一条带有投票评论的文章...
$posts = App\Post::has('comments.votes')->get();
传递给 hasOneThrough
方法的第一个参数是希望访问的模型名称,第二个参数是中间模型的名称。
当执行关联查询时,通常会使用 Eloquent 约定的外键名。如果你想要自定义关联的键,可以通过给 hasOneThrough
Role 모델의 연관을 작성할 때 사용자 정의 중간 테이블 모델인 UserRole
을 사용합니다.
use Illuminate\Database\Eloquent\Builder;
// 获取至少带有一条评论内容包含 foo% 关键词的文章...
$posts = App\Post::whereHas('comments', function ($query)
{
$query->where('content', 'like', 'foo%');})->get();
// 获取至少带有十条评论内容包含 foo% 关键词的文章...
$posts = App\Post::whereHas('comments', function ($query)
{
$query->where('content', 'like', 'foo%');
}, '>=', 10)->get();
UserRole
모델을 정의할 때, Pivot
클래스: $posts = App\Post::doesntHave('comments')->get();
using
과 withPivot
을 조합하여 중간 테이블에서 열을 검색할 수 있습니다. 예를 들어 created_by
및 updated_by
는 열 이름을 withPivot
에 전달하여 UserRole
중간 테이블에서 검색할 수 있습니다. method > 두 개의 데이터 열.
use Illuminate\Database\Eloquent\Builder;
$posts = App\Post::whereDoesntHave('comments', function (Builder $query)
{
$query->where('content', 'like', 'foo%');
})->get();
ID가 증가하는 사용자 정의 릴레이 모델
사용자 정의 릴레이 모델 다중 관계로 여러 쌍을 정의하고 릴레이 모델에 자동 증가 기본 키인 경우 사용자 정의 릴레이 모델 클래스가 true
값으로 incrementing
속성을 정의하는지 확인해야 합니다. one-through">🎜🎜🎜🎜원격 일대일 관계🎜🎜중개 연결 모델 구현을 통한 원격 일대일 연결. 🎜예를 들어, 각 제공업체에 사용자가 있고 각 사용자가 사용자 기록과 연결되어 있는 경우 제공업체는 사용자를 통해 사용자의 기록에 액세스할 수 있습니다. 이 관계를 정의하는 데 필요한 데이터베이스 테이블을 살펴보겠습니다. 🎜use Illuminate\Database\Eloquent\Builder;
$posts = App\Post::whereDoesntHave('comments.author', function (Builder $query)
{
$query->where('banned', 1);
})->get();
🎜 history
테이블에 supplier_id
가 포함되어 있지 않으면 hasOneThrough
관계를 통해 사용자 기록에 대한 액세스를 제공하여 공급업체 모델에 액세스할 수 있습니다. 이제 관계의 테이블 구조를 검사했으므로 Supplier
모델에서 해당 메서드를 정의해 보겠습니다. 🎜$posts = App\Post::withCount('comments')->get();
foreach ($posts as $post) {
echo $post->comments_count;
}
🎜 hasOneThrough
메서드에 전달된 첫 번째 매개변수는 원하는 매개변수입니다. access 모델 이름, 두 번째 매개변수는 중간 모델의 이름입니다. 🎜🎜관련 쿼리를 실행할 때 일반적으로 Eloquent의 기존 외래 키 이름이 사용됩니다. 연관된 키를 사용자 정의하려면 세 번째 및 네 번째 매개변수를 hasOneThrough
메소드에 전달하면 됩니다. 세 번째 매개변수는 중간 모델의 외래 키 이름을 나타내고, 네 번째 매개변수는 나타냅니다. 최종 모델의 외래 키 이름입니다. 다섯 번째 매개변수는 로컬 키 이름을 나타내고, 여섯 번째 매개변수는 중간 모델의 로컬 키 이름을 나타냅니다. 🎜$posts = App\Post::withCount(['votes', 'comments' => function ($query)
{
$query->where('content', 'like', 'foo%');
}])->get();
echo $posts[0]->votes_count;echo $posts[0]->comments_count;
🎜🎜🎜🎜🎜🎜원격 일대다 연결
원격 일대다 연결은 중간 연결을 통해 원격 수준 연결을 얻는 편리하고 짧은 방법을 제공합니다. 예를 들어 Country
모델은 중간 User
모델을 통해 여러 Post
모델을 가질 수 있습니다. 이 예에서는 특정 국가의 모든 블로그 게시물을 쉽게 수집할 수 있습니다. 이 연결을 정의하는 데 필요한 데이터 테이블을 살펴보겠습니다. Country
模型可以通过中间的 User
模型获得多个 Post
模型。在这个例子中,你可以轻易地收集给定国家的所有博客文章。让我们来看看定义这种关联所需的数据表:
$posts = App\Post::withCount([
'comments',
'comments as pending_comments_count' => function ($query) {
$query->where('approved', false);
}])->get();
echo $posts[0]->comments_count;
echo $posts[0]->pending_comments_count;
虽然 posts
表中不包含 country_id
字段,但 hasManyThrough
关联能让我们通过 $country->posts
访问到一个国家下所有的用户文章。为了完成这个查询,Eloquent 会先检查中间表 users
的 country_id
字段,找到所有匹配的用户 ID 后,使用这些 ID,在 posts
表中完成查找。
现在,我们已经知道了定义这种关联所需的数据表结构,接下来,让我们在 Country
模型中定义它:
$query = App\Post::select(['title', 'body'])->withCount('comments');
echo $posts[0]->title;
echo $posts[0]->body;
echo $posts[0]->comments_count;
hasManyThrough
方法的第一个参数是我们最终希望访问的模型名称,而第二个参数是中间模型的名称。
当执行关联查询时,通常会使用 Eloquent 约定的外键名。如果你想要自定义关联的键,可以通过给 hasManyThrough
方法传递第三个和第四个参数实现,第三个参数表示中间模型的外键名,第四个参数表示最终模型的外键名。第五个参数表示本地键名,而第六个参数表示中间模型的本地键名:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Book extends Model{
/**
* 获取书籍作者。
*/
public function author()
{
return $this->belongsTo('App\Author');
}
}
多态关联
多态关联允许目标模型借助单个关联从属于多个模型。
一对一(多态)
表结构
一对一多态关联与简单的一对一关联类似;不过,目标模型能够在一个关联上从属于多个模型。例如,博客 Post
和 User
可能共享一个关联到 Image
模型的关系。使用一对一多态关联允许使用一个唯一图片列表同时用于博客文章和用户账户。让我们先看看表结构:
$books = App\Book::all();
foreach ($books as $book)
{
echo $book->author->name;
}
要特别留意 images
表的 imageable_id
和 imageable_type
列。 imageable_id
列包含文章或用户的 ID 值,而 imageable_type
列包含的则是父模型的类名。Eloquent 在访问 imageable
时使用 imageable_type
$books = App\Book::with('author')->get();
foreach ($books as $book) {
echo $book->author->name;
}
posts
테이블에는 country_id
필드가 포함되어 있지 않지만 hasManyThrough
연결을 통해 $country->posts
를 통해 한 국가의 모든 사용자 게시물에 액세스할 수 있습니다. 이 쿼리를 완료하기 위해 Eloquent는 먼저 중간 테이블 users
의 country_id
필드를 확인한 후 일치하는 모든 사용자 ID를 찾은 후 이 ID를 사용하여 에 게시합니다. 게시물
표에서 검색을 완료하세요. 이제 이 연관을 정의하는 데 필요한 데이터 테이블 구조를 알았으므로 이를 Country
모델에서 정의해 보겠습니다. select * from books
select * from authors where id in (1, 2, 3, 4, 5, ...)
hasManyThrough
메소드 첫 번째 매개변수는 우리가 궁극적으로 접근하고자 하는 모델이고, 두 번째 매개변수는 중간 모델의 이름입니다. 관련 쿼리를 실행할 때 일반적으로 Eloquent의 기존 외래 키 이름이 사용됩니다. 연관된 키를 사용자 정의하려면 세 번째 및 네 번째 매개변수를 hasManyThrough
메소드에 전달하면 됩니다. 세 번째 매개변수는 중간 모델의 외래 키 이름을 나타내고 네 번째 매개변수는 나타냅니다. 최종 모델의 외래 키 이름입니다. 다섯 번째 매개변수는 로컬 키 이름을 나타내고, 여섯 번째 매개변수는 중간 모델의 로컬 키 이름을 나타냅니다. $books = App\Book::with(['author', 'publisher'])->get();
🎜🎜다형성 연관
🎜다형성 연관을 사용하면 대상 모델이 단일 연관을 통해 여러 모델에 종속될 수 있습니다. 🎜🎜🎜🎜🎜일대일(다형성)🎜< div name="03a0d2" data-unique="03a0d2">🎜🎜테이블 구조🎜🎜일대일 다형성 연관은 단순한 일대일 연관과 유사하지만 대상 모델은 여러 모델에 속할 수 있습니다. 단일 협회. 예를 들어 블로그 Post
및 User
는 Image
모델과 관계를 공유할 수 있습니다. 일대일 다형성 연관을 사용하면 블로그 게시물과 사용자 계정 모두에 대해 고유한 이미지 목록을 사용할 수 있습니다. 먼저 테이블 구조를 살펴보겠습니다. 🎜$books = App\Book::with('author.contacts')->get();
🎜 images
테이블의 imageable_id
및 imageable_type
열에 특히 주의하세요. imageable_id
열에는 게시물 또는 사용자 ID 값이 포함되고, imageable_type
열에는 상위 모델의 클래스 이름이 포함됩니다. Eloquent는 imageable
에 액세스할 때 상위 모델의 "유형"을 결정하기 위해 imageable_type
열을 사용합니다. 🎜🎜🎜🎜모델 구조🎜🎜다음으로 연관을 설정하기 위한 모델 정의를 살펴보겠습니다. 🎜$users = App\Book::with('author:id,name')->get();
🎜🎜연관 가져오기
테이블과 모델이 정의되면 모델을 통해 이 연관에 액세스할 수 있습니다. 예를 들어, 기사 이미지를 얻으려면 image
동적 속성을 사용할 수 있습니다: image
动态属性:
$users = App\User::with(['posts' => function ($query) {
$query->where('title', 'like', '%first%');
}])->get();
还可以通过访问执行 morphTo
调用的方法名来从多态模型中获知父模型。在这个例子中,就是 Image
模型的 imageable
方法。所以,我们可以像动态属性那样访问这个方法:
$users = App\User::with(['posts' => function ($query) {
$query->orderBy('created_at', 'desc');
}])->get();
Image
模型的 imageable
关联将返回 Post
或 User
实例,其结果取决于图片属性哪个模型。
一对多(多态)
表结构
一对多多态关联与简单的一对多关联类似;不过,目标模型可以在一个关联中从属于多个模型。假设应用中的用户可以同时 「评论」 文章和视频。使用多态关联,可以用单个 comments
表同时满足这些情况。我们还是先来看看用来构建这种关联的表结构:
$books = App\Book::all();
if ($someCondition) {
$books->load('author', 'publisher');
}
模型结构
接下来,看看构建这种关联的模型定义:
$books->load(['author' => function ($query) {
$query->orderBy('published_date', 'asc');
}]);
获取关联
一旦定义了数据库表和模型,就可以通过模型访问关联。例如,可以使用 comments
动态属性访问文章的全部评论:
public function format(Book $book){
$book->loadMissing('author');
return [
'name' => $book->name,
'author' => $book->author->name
];
}
还可以通过访问执行 morphTo
调用的方法名来从多态模型获取其所属模型。在本例中,就是 Comment
模型的 commentable
方法:
<?php
use Illuminate\Database\Eloquent\Model;
class ActivityFeed extends Model{
/**
* Get the parent of the activity feed record.
*/
public function parentable()
{
return $this->morphTo();
}
}
Comment
模型的 commentable
关联将返回 Post
或 Video
实例,其结果取决于评论所属的模型。
多对多(多态)
表结构
多对多多态关联比 morphOne
和 morphMany
关联略微复杂一些。例如,博客 Post
和 Video
模型能够共享关联到 Tag
模型的多态关系。使用多对多多态关联允许使用一个唯一标签在博客文章和视频间共享。以下是多对多多态关联的表结构:
$activities = ActivityFeed::with('parentable')
->get()
->loadMorph('parentable', [
Event::class => ['calendar'],
Photo::class => ['tags'],
Post::class => ['author'],
]);
模型结构
接下来,在模型上定义关联。Post
和 Video
模型都有调用 Eloquent 基类上 morphToMany
方法的 tags
$comment = new App\Comment(['message' => 'A new comment.']);
$post = App\Post::find(1);
$post->comments()->save($comment);
또한 morphTo를 실행하는 메서드 이름에 액세스하여 다형성 모델에서 상위 모델을 가져올 수도 있습니다.
전화하세요. 이 경우 Image
모델의 imageable
메서드입니다. 따라서 동적 속성처럼 이 메서드에 액세스할 수 있습니다. $post = App\Post::find(1);
$post->comments()->saveMany([
new App\Comment(['message' => 'A new comment.']),
new App\Comment(['message' => 'Another comment.']),
]);
Image
모델의 imageable
연결은 Post
또는 User를 반환합니다.
인스턴스의 경우 이미지 속성이 어떤 모델인지에 따라 결과가 달라집니다. 🎜🎜🎜🎜일대다(다형성) < /h3>🎜🎜테이블 구조🎜🎜일대다 다형성 연관은 단순한 일대다 연관과 유사하지만 대상 모델은 다음과 같습니다. 하나의 연관 모델에서 다수에 종속됩니다. 애플리케이션의 사용자가 기사와 비디오에 동시에 "댓글"을 달 수 있다고 가정합니다. 다형성 연관을 사용하면 단일 comments
테이블로 이러한 상황을 모두 충족할 수 있습니다. 먼저 이 연관을 구축하는 데 사용된 테이블 구조를 살펴보겠습니다. 🎜$post = App\Post::find(1);
$post->comments[0]->message = 'Message';
$post->comments[0]->author->name = 'Author Name';$post->push();
🎜🎜모델 구조🎜🎜다음으로 이 연관을 구축하는 모델을 살펴보겠습니다. : 🎜$post = App\Post::find(1);
$comment = $post->comments()->create([
'message' => 'A new comment.',
]);
🎜🎜연관 가져오기 🎜🎜데이터베이스 테이블과 모델이 정의되면 모델을 통해 연관에 접근할 수 있습니다. 예를 들어, comments
동적 속성을 사용하여 기사의 모든 댓글에 액세스할 수 있습니다: 🎜$post = App\Post::find(1);$post->comments()->createMany([
[
'message' => 'A new comment.',
],
[
'message' => 'Another new comment.',
],
]);
🎜 또한 다음 작업을 수행하는 메서드의 이름에 액세스하여 다형성 모델에서 해당 댓글이 속한 모델을 가져올 수도 있습니다. morphTo
호출. 이 경우 Comment
모델의 commentable
메서드: 🎜$account = App\Account::find(10);
$user->account()->associate($account);$user->save();
🎜 Comment
모델의 commentable
연결은 를 반환합니다. >게시물
또는 동영상
인스턴스의 경우 결과는 댓글이 속한 모델에 따라 다릅니다. 🎜🎜🎜🎜다대다(다형성) < /h3>🎜🎜테이블 구조🎜🎜다대다 다형성 연관은 morphOne
및 morphMany보다 약간 더 복잡합니다.
연관 일부. 예를 들어 블로그 게시물
및 동영상
모델은 태그
모델과 다형성 관계를 공유할 수 있습니다. 다대다 다형성 연관을 사용하면 고유한 태그를 사용하여 블로그 게시물과 비디오를 공유할 수 있습니다. 다음은 다대다 다형성 연관의 테이블 구조입니다: 🎜$user->account()->dissociate();$user->save();
🎜🎜모델 구조🎜🎜다음으로, 모델에 대한 연관을 정의합니다. Post
및 Video
모델 모두 Eloquent 기본 클래스에서 morphToMany
메서드를 호출하는 tags
메서드가 있습니다. 🎜/**
* 获取帖子的作者。
*/
public function user(){
return $this->belongsTo('App\User')->withDefault();
}
🎜🎜역방향 연관 관계 정의
다음으로 Tag
모델에서 각 연관 모델에 대한 메소드를 정의해야 합니다. 이 예에서는 posts
메소드와 videos
메소드를 정의합니다: Tag
模型上为每个关联模型定义一个方法。在这个示例中,我们将会定义 posts
方法和 videos
方法:
/**
* 获取帖子的作者。
*/
public function user(){
return $this->belongsTo('App\User')->withDefault([
'name' => 'Guest Author',
]);
}
/**
* 获取帖子的作者。
*/
public function user(){
return $this->belongsTo('App\User')->withDefault(function ($user) {
$user->name = 'Guest Author';
});
}
获取关联
一旦定义了数据库表和模型,就可以通过模型访问关联。例如,可以使用 tags
动态属性访问文章的所有标签:
$user = App\User::find(1);
$user->roles()->attach($roleId);
还可以访问执行 morphedByMany
方法调用的方法名来从多态模型获取其所属模型。在这个示例中,就是 Tag
模型的 posts
或 videos
方法。可以像动态属性一样访问这些方法:
$user->roles()->attach($roleId, ['expires' => $expires]);
自定义多态类型
默认情况下, Laravel 使用完全限定类名存储关联模型类型。在上面的一对多示例中, 因为 Comment
可能从属于一个 Post
或一个 Video
,默认的 commentable_type
就将分别是 AppPost
或 AppVideo
。不过,你可能希望数据库与应用的内部结构解耦。在这种情况下,可以定义一个 「morph 映射」 来通知 Eloquent 使用自定义名称代替对应的类名:
// 移除用户的一个角色...
$user->roles()->detach($roleId);
// 移除用户的所有角色...
$user->roles()->detach();
可以在 AppServiceProvider
的 boot
函数中注册 morphMap
,或者创建一个单独的服务提供者。
查询关联
由于 Eloquent 关联的所有类型都通过方法定义,你可以调用这些方法,而无需真实执行关联查询。另外,所有 Eloquent 关联类型用作 查询构造器,允许你在数据库上执行 SQL 之前,持续通过链式调用添加约束。
例如,假设一个博客系统的 User
模型有许多关联的 Post
模型:
$user = App\User::find(1);
$user->roles()->detach([1, 2, 3]);
$user->roles()->attach([
1 => ['expires' => $expires],
2 => ['expires' => $expires]
]);
你可以查询 posts
$user->roles()->sync([1, 2, 3]);
Get 연관
데이터베이스 테이블과 모델이 정의되면 모델을 통해 관계에 접근할 수 있습니다. 예를 들어 tags
동적 속성을 사용하여 기사의 모든 태그에 액세스할 수 있습니다. $user->roles()->sync([1 => ['expires' => true], 2, 3]);
또한 morphedByMany
메소드 호출을 실행하는 메소드 이름에 액세스하여 다형성 모델에 속하는 모델입니다. 이 예에서는 Tag
모델의 posts
또는 videos
메서드입니다. 이러한 메소드는 동적 속성처럼 액세스할 수 있습니다:
$user->roles()->syncWithoutDetaching([1, 2, 3]);
🎜🎜사용자 정의 다형성 유형 h3>🎜기본적으로 Laravel은 정규화된 클래스 이름을 사용하여 관련 모델 유형을 저장합니다. 위의 일대다 예에서 댓글
은 게시물
또는 동영상
에 속할 수 있으므로 기본 commentable_type code >는 각각 AppPost
또는 AppVideo
입니다. 그러나 애플리케이션의 내부 구조에서 데이터베이스를 분리할 수도 있습니다. 이 경우 "모프 매핑"을 정의하여 해당 클래스 이름 대신 사용자 정의 이름을 사용하도록 Eloquent에 알릴 수 있습니다. 🎜$user->roles()->toggle([1, 2, 3]);
🎜 AppServiceProvider<의 boot
함수에서 수행할 수 있습니다. /code> morphMap
을 등록하거나 별도의 서비스 공급자를 만듭니다. 🎜🎜🎜🎜🎜관계 쿼리
🎜모든 유형의 Eloquent 관계는 메소드를 통해 정의되므로 , 관련 쿼리를 실제로 실행하지 않고도 이러한 메서드를 호출할 수 있습니다. 또한 모든 Eloquent 관계 유형은 쿼리 빌더 역할을 하여 데이터베이스에서 SQL을 실행하기 전에 호출 체인을 통해 지속적으로 제약 조건을 추가할 수 있습니다. 🎜🎜예를 들어, 블로그 시스템의 User
모델에 연결된 Post
모델이 많이 있다고 가정해 보세요. 🎜App\User::find(1)->roles()->save($role, ['expires' => $expires]);
🎜posts
연결을 쿼리하고 이를 제공할 수 있습니다. 추가 제약 조건 추가: 🎜$user = App\User::find(1);
$user->roles()->updateExistingPivot($roleId, $attributes);
🎜 연결에서 쿼리 빌더 방법을 사용할 수 있습니다. 어떤 방법이 유용할지 알아보려면 쿼리 빌더 설명서를 참조하세요. 🎜🎜🎜🎜🎜🎜🎜Relation Methods Vs. Dynamic Properties
Eloquent 관계 쿼리에 추가 제약 조건을 추가할 필요가 없다면 속성처럼 관계에 액세스할 수 있습니다. 예를 들어 User
및 Post
예제 모델을 계속 사용하면 다음과 같이 사용자의 모든 게시물에 액세스할 수 있습니다. User
和 Post
示例模型,可以这样访问用户的全部文章:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model{
/**
* 要触发的所有关联关系
*
* @var array
*/
protected $touches = ['post'];
/**
* 评论所属的文章
*/
public function post()
{
return $this->belongsTo('App\Post');
}
}
动态属性是「懒加载」的,这意味着它们仅在你真实访问关联数据时才被载入。因此,开发者经常使用 预加载 预先加载那些他们确知在载入模型后将访问的关联。对载入模型关联中必定被执行的 SQL 查询而言,预加载显著减少了查询的执行次数。
查询已存在的关联
在访问模型记录时,可能希望基于关联的存在限制查询结果。比如想要获取至少存在一条评论的所有文章,可以通过给 has
和 orHas
方法传递关联名称来实现:
$comment = App\Comment::find(1);
$comment->text = 'Edit to this comment!';
$comment->save();
还可以指定运算符和数量进一步自定义查询:
rrreee还可以用 「点」语法构造嵌套的 has
语句。比如,可以获取拥有至少一条评论和投票的文章:
rrreee如果需要更多功能,可以使用 whereHas
和 orWhereHas
方法将「where」 条件放到 has
查询上。这些方法允许你向关联加入自定义约束,比如检查评论内容:
rrreee查询不存在的关联
在访问模型记录时,可能希望基于关联不存在来限制查询结果。假设想要获取不存在任何评论的文章,可以通过向 doesntHave
和 orDoesntHave
方法传递关联名称来实现:
rrreee如果需要更多功能,可以使用 whereDoesntHave
和 orWhereDoesntHave
方法将「where」 条件加到 doesntHave
rrreee
동적 속성은 "지연 로드"됩니다. 연결된 데이터가 실제로 액세스할 때만 로드된다는 의미입니다. 따라서 개발자는 종종 eager-loading을 사용하여 모델을 로드한 후 액세스하게 될 관계를 미리 로드합니다. 모델 연결을 로드할 때 실행해야 하는 SQL 쿼리의 경우 즉시 로드를 사용하면 쿼리 실행 횟수가 크게 줄어듭니다.
기존 관계 쿼리🎜모델 레코드에 액세스할 때 다음을 기반으로 할 수 있습니다. 관계의 존재는 쿼리 결과를 제한합니다. 예를 들어, 댓글이 하나 이상 포함된 모든 기사를 가져오려면 연결 이름을 has
및 orHas
메소드에 전달할 수 있습니다. 🎜rrreee🎜 또한 지정할 수도 있습니다 추가 사용자 정의 쿼리를 위한 연산자 및 수량: 🎜rrreee🎜 "점" 구문을 사용하여 중첩된 has
문을 구성할 수도 있습니다. 예를 들어, 댓글과 투표가 하나 이상 포함된 기사를 얻을 수 있습니다. 🎜rrreee🎜더 많은 기능이 필요한 경우 whereHas
및 orWhereHas
메소드를 사용하여 " < code>has 쿼리의 where" 조건입니다. 이러한 방법을 사용하면 댓글 내용 확인과 같은 관계에 사용자 지정 제약 조건을 추가할 수 있습니다. 🎜rrreee🎜🎜🎜🎜🎜 존재하지 않는 관계에 대한 쿼리🎜🎜모델 레코드에 액세스할 때 관계가 존재하지 않음을 기준으로 쿼리 결과를 제한할 수 있습니다. 댓글이 없는 기사를 가져오려고 한다고 가정해 보겠습니다. doesntHave
및 orDoesntHave
메소드에 연결 이름을 전달하면 됩니다. 🎜 rrreee🎜필요한 경우 더 많은 기능을 사용하려면 whereDoesntHave
및 orWhereDoesntHave
메서드를 사용하여 doesntHave
쿼리에 "where" 조건을 추가할 수 있습니다. 이러한 방법을 사용하면 댓글 내용 감지와 같은 연결에 사용자 정의 제한을 추가할 수 있습니다. 🎜rrreee🎜 "점" 구문을 사용하여 중첩된 연결 쿼리를 수행할 수도 있습니다. 예를 들어, 금지되지 않은 작성자의 댓글이 포함된 기사를 가져오는 데 다음 쿼리가 사용됩니다. 🎜rrreee🎜🎜🎜🎜🎜🎜관계 모델 개수
연관 결과를 실제로 로드하지 않고 통계적인 개수만 계산하려는 경우 {relation}_count에 배치되는 withCount
메서드를 사용할 수 있습니다. < 결과 모델 /code> 열. 예는 다음과 같습니다. withCount
方法,它将放在结果模型的 {relation}_count
列。示例如下:
rrreee可以像给查询添加限制一样为多个关系添加「计数」:
rrreee还可以给关联计数结果起别名,这允许你在同一关联上添加多个计数:
rrreee如果将 withCount
和 select
查询组装在一起,请确保在 select
方法之后调用 withCount
:
rrreee预加载
当以属性方式访问 Eloquent 关联时,关联数据「懒加载」。这着直到第一次访问属性时关联数据才会被真实加载。不过 Eloquent 能在查询父模型时「预先载入」子关联。预加载可以缓解 N + 1 查询问题。为了说明 N + 1 查询问题,考虑 Book
模型关联到 Author
的情形:
rrreee现在,我们来获取所有的书籍及其作者:
rrreee此循环将执行一个查询,用于获取全部书籍,然后为每本书执行获取作者的查询。如果我们有 25 本书,此循环将运行 26 个查询:1 个用于查询书籍,25 个附加查询用于查询每本书的作者。
谢天谢地,我们能够使用预加载将操作压缩到只有 2 个查询。在查询时,可以使用 with
方法指定想要预加载的关联:
rrreee在这个例子中,仅执行了两个查询:
rrreee预加载多个关联
有时,你可能需要在单一操作中预加载几个不同的关联。要达成此目的,只要向 with
方法传递多个关联名称构成的数组参数:
rrreee嵌套预加载
可以使用 「点」 语法预加载嵌套关联。比如在一个 Eloquent 语句中预加载所有书籍作者及其联系方式:
rrreee预加载指定列
并不是总需要获取关系的每一列。在这种情况下,Eloquent 允许你为关联指定想要获取的列:
rrreee{note} 在使用这个特性时,一定要在要获取的列的列表中包含 id
rrreee
쿼리에 제한을 추가하는 것처럼 여러 관계에 "개수"를 추가할 수 있습니다.
rrreee 또한 관계 개수 결과에 별칭을 지정하여 동일한 관계에 여러 개수를 추가할 수도 있습니다. rrreeewithCount
및 select
쿼리를 함께 조합하려면 select
메서드 다음에 withCount
를 호출해야 합니다.
rrreee< a name="eager-loading">🎜🎜Eager-loading
🎜Eloquent 연결을 속성으로 액세스하는 경우 , 관련 데이터는 "지연" 로드입니다. 이렇게 하면 속성에 처음 액세스할 때까지 관련 데이터가 실제로 로드되지 않습니다. 그러나 Eloquent는 상위 모델을 쿼리할 때 하위 관계를 "미리 로드"할 수 있습니다. 즉시 로딩은 N+1 쿼리 문제를 완화할 수 있습니다. N + 1 쿼리 문제를 설명하기 위해 Book
모델이 Author
와 연결된 경우를 생각해 보세요. 🎜rrreee🎜이제 모든 책과 해당 저자를 가져오겠습니다. 🎜 rrreee🎜This 루프는 모든 책을 가져오는 쿼리를 실행한 다음 각 책에 대해 저자를 가져오는 쿼리를 실행합니다. 25권의 책이 있는 경우 이 루프는 26개의 쿼리를 실행합니다. 1개는 책을 쿼리하고 25개의 추가 쿼리는 각 책의 저자를 쿼리합니다. 🎜🎜다행히 Eager 로딩을 사용하여 작업을 단 2개의 쿼리로 압축할 수 있었습니다. 쿼리 시 with
메서드를 사용하여 미리 로드할 연결을 지정할 수 있습니다. 🎜rrreee🎜이 예에서는 두 개의 쿼리만 실행되었습니다: 🎜rrreee🎜여러 연결 미리 로드
🎜때때로 단일 작업에서 여러 다른 연결을 미리 로드해야 할 수도 있습니다. 이를 달성하려면 여러 개의 연관된 이름으로 구성된 배열 매개변수를 with
메소드에 전달하면 됩니다: 🎜rrreee🎜중첩된 사전 설정
🎜"점" 구문을 사용하여 중첩된 연결을 미리 로드할 수 있습니다. 예를 들어, 하나의 Eloquent 문에 모든 책 저자와 연락처 정보를 미리 로드합니다: 🎜rrreee🎜지정된 열을 미리 로드
🎜하는 것이 항상 필요한 것은 아닙니다. 관계의 각 열. 이 경우, Eloquent를 사용하면 연결에 대해 얻고 싶은 열을 지정할 수 있습니다: 🎜rrreee🎜{note} 이 기능을 사용할 때 가져올 열 목록에 id를 포함해야 합니다. .코드> 열. 🎜🎜🎜🎜🎜🎜🎜🎜미리 로드에 대한 제약 조건 추가
때때로 다음 예와 같이 추가 쿼리 조건을 사전 로드 쿼리에 추가하는 동안 관계를 사전 로드할 수도 있습니다:
rrreee이 예에서 Eloquent는 제목이 < /code> 열에는 first
키워드가 포함되어 있습니다. 다른 쿼리 빌더 메서드를 호출하여 사전 로드 작업을 추가로 사용자 정의할 수도 있습니다. title
列包含 first
关键词的文章。也可以调用其它的 查询构造器 方法进一步自定义预加载操作:
rrreee{note} 在约束预加载时,不能使用 limit
和 take
查询构造器方法。
预加载
有可能你还希望在模型加载完成后在进行渴求式加载。举例来说,如果你想要动态的加载关联数据,那么 load
方法对你来说会非常有用:
rrreee如果你想要在渴求式加载的查询语句中进行条件约束,你可以通过数组的形式去加载,键为对应的关联关系,值为 Closure
闭包函数,该闭包的参数为一个 query
实例:
rrreee当关联关系没有被加载时,你可以使用 loadMissing
方法:
rrreee嵌套延迟加载 & morphTo
如果希望快速加载 morphTo
关系,以及该关系可能返回的各种实体上的嵌套关系,可以使用 loadMorph
方法。
这个方法接受 morphTo
关系的名称作为它的第一个参数,第二个参数接收模型数组、关系数组。为了帮助说明这个方法,可以看一下以下模型例子:
rrreee在这个例子中,让我们假设 Event
、Photo
和 Post
模型可以创建 ActivityFeed
模型。此外,让我们假设 Event
模型属于 Calendar
模型,Photo
模型与 Tag
模型相关联,Post
模型属于 Author
模型。
使用这些模型定义和关系,我们可以检索 ActivityFeed
模型实例,并立即加载所有 parentable
rrreee
{note} 사전 로드를 제한하는 경우 limit
및 take
쿼리 빌더를 사용할 수 없습니다. 방법.
Preloading모델 로딩을 완료하고 싶을 수도 있습니다. 그런 다음 목마른 로딩을 수행합니다. 예를 들어 관련 데이터를 동적으로 로드하려는 경우 load
메서드가 매우 유용할 것입니다. rrreee Eager Loading 쿼리 문에서 조건부로 제한하려는 경우 로드할 수 있습니다. 배열 형식이며 키는 해당 연결이고 값은 Closure
클로저 함수이고 클로저의 매개변수는 query
인스턴스입니다. rrreee
연관이 로드되지 않은 경우 loadMissing
메소드를 사용할 수 있습니다: rrreee중첩 지연 로딩& morphTo< /code>
🎜morphTo
관계뿐만 아니라 관계가 반환할 수 있는 다양한 엔터티의 중첩 관계를 빠르게 로드하려면 loadMorph
방법. 🎜🎜이 메소드는 morphTo
관계의 이름을 첫 번째 매개변수로 받아들이고, 두 번째 매개변수는 모델 배열과 관계 배열을 받습니다. 이 접근 방식을 설명하는 데 도움이 되도록 다음 모델 예를 살펴보십시오. 🎜rrreee🎜이 예에서는 Event
, Photo
및 Post
를 가정하겠습니다. 모델은 ActivityFeed
모델을 생성할 수 있습니다. 또한 Event
모델이 Calendar
모델에 속하고 Photo
모델이 Tag
모델이고 Post
모델은 Author
모델에 속합니다. 🎜🎜이러한 모델 정의 및 관계를 사용하여 ActivityFeed
모델 인스턴스를 검색하고 모든 부모 가능
모델과 각각의 중첩 관계를 한 번에 로드할 수 있습니다. 🎜rrreee🎜🎜🎜🎜 🎜 🎜🎜관련 모델 삽입 및 업데이트🎜🎜🎜🎜🎜🎜🎜저장 방법
Eloquent는 새 모델에 연관을 추가하는 편리한 방법을 제공합니다. 예를 들어 게시물
모델에 새 댓글
을 추가해야 할 수도 있습니다. Comment
에서 post_id
속성을 수동으로 설정할 필요가 없으며, 관련 모델의 save
메소드를 직접 사용하여 를 저장할 수 있습니다. >Comment
직접 삽입: Comment
到一个 Post
模型中。你不用在 Comment
中手动设置 post_id
属性,就可以直接使用关联模型的 save
方法将 Comment
直接插入:
rrreee需要注意的是,我们并没有使用动态属性的方式访问 comments
关联。相反,我们调用 comments
方法来获得关联实例。save
方法将自动添加适当的 post_id
值到 Comment
模型中。
如果你需要保存多个关联模型,你可以使用 saveMany
方法:
rrreee递归保存模型和关联数据
如果你想 save
你的模型及其所有关联数据,你可以使用 push
方法:
rrreee新增方法
除了 save
和 saveMany
方法外,你还可以使用 create
方法。它接受一个属性数组,同时会创建模型并插入到数据库中。 还有, save
方法和 create
方法的不同之处在于, save
方法接受一个完整的 Eloquent 模型实例,而 create
则接受普通的 PHP 数组:
rrreee{tip} 在使用 create
方法前,请务必确保查看过本文档的 批量赋值 章节。
你还可以使用 createMany
方法去创建多个关联模型:
rrreee你还可以使用 findOrNew
、firstOrNew
、firstOrCreate
和 updateOrCreate
方法来 创建和更新关系模型.
更新 belongsTo
关联
当更新 belongsTo
关联时,可以使用 associate
方法。此方法将会在子模型中设置外键:
rrreee当移除 belongsTo
关联时,可以使用 dissociate
方法。此方法会将关联外键设置为 null
rrreee
comments
연결에 액세스하기 위해 동적 속성을 사용하지 않는다는 점에 유의해야 합니다. 대신 comments
메서드를 호출하여 관련 인스턴스를 가져옵니다. save
메소드는 적절한 post_id
값을 Comment
모델에 자동으로 추가합니다. 여러 관련 모델을 저장해야 하는 경우 saveMany
메서드를 사용할 수 있습니다. rrreee
🎜모델 및 관련 데이터를 반복적으로 저장
🎜모델 및 모든 관련 데이터를 저장
하려면 push<를 사용할 수 있습니다. / code> 방법:🎜rrreee🎜🎜🎜🎜🎜새 방법🎜🎜저장 제외 code> 및 saveMany
메소드 외에도 create
메소드를 사용할 수도 있습니다. 이는 속성 배열을 받아들이고 모델을 생성하여 데이터베이스에 삽입합니다. 또한 save
메소드와 create
메소드의 차이점은 save
메소드는 완전한 Eloquent 모델 인스턴스를 허용하는 반면 create
는 일반 PHP 배열을 허용합니다: 🎜rrreee🎜{tip} create
메서드를 사용하기 전에 이 문서의 일괄 할당 장을 확인하세요. 🎜
🎜 createMany
메서드를 사용하여 여러 관련 모델을 만들 수도 있습니다. 🎜rrreee🎜 findOrNew
, firstOrNew
를 사용할 수도 있습니다. , firstOrCreate
및 updateOrCreate
메소드를 사용하여 관계 모델을 생성하고 업데이트합니다.🎜🎜🎜🎜🎜🎜belongsTo
연결 업데이트 🎜🎜belongsTo
연결을 업데이트할 때 associate
메서드를 사용할 수 있습니다 . 이 메소드는 하위 모델에 외래 키를 설정합니다: 🎜rrreee🎜 belongsTo
연관을 제거할 때 dissociate
메소드를 사용할 수 있습니다. 이 메소드는 연관된 외래 키를 null
로 설정합니다:🎜rrreee🎜🎜🎜🎜🎜🎜기본 모델
belongsTo
관계를 사용하면 기본 모델을 지정할 수 있습니다. 주어진 관계가 null
이면 기본 모델이 반환됩니다. 이 패턴을 Null 객체 패턴이라고 하며 코드에서 불필요한 검사를 줄일 수 있습니다. 아래 예에서 게시된 게시물의 작성자를 찾을 수 없는 경우 user
관계는 빈 AppUser
모델을 반환합니다. belongsTo
关系允许你指定默认模型,当给定关系为 null
时,将会返回默认模型。 这种模式被称作 Null 对象模式 ,可以减少你代码中不必要的检查。在下面的例子中,如果发布的帖子没有找到作者, user
关系会返回一个空的 AppUser
模型:
rrreee如果需要在默认模型里添加属性, 你可以传递数组或者回调方法到 withDefault
中:
rrreee多对多关联
附加 / 分离
Eloquent 也提供了一些额外的辅助方法,使相关模型的使用更加方便。例如,我们假设一个用户可以拥有多个角色,并且每个角色都可以被多个用户共享。给某个用户附加一个角色是通过向中间表插入一条记录实现的,可以使用 attach
方法完成该操作:
rrreee在将关系附加到模型时,还可以传递一组要插入到中间表中的附加数据:
rrreee当然,有时也需要移除用户的角色。可以使用 detach
移除多对多关联记录。detach
方法将会移除中间表对应的记录;但是这 2 个模型都将会保留在数据库中:
rrreee为了方便,attach
和 detach
也允许传递一个 ID 数组:
rrreee同步关联
你也可以使用 sync
方法构建多对多关联。sync
方法接收一个 ID 数组以替换中间表的记录。中间表记录中,所有未在 ID 数组中的记录都将会被移除。所以该操作结束后,只有给出数组的 ID 会被保留在中间表中:
rrreee你也可以通过 ID 传递额外的附加数据到中间表:
rrreee如果你不想移除现有的 ID,可以使用 syncWithoutDetaching
方法:
rrreee切换关联
多对多关联也提供了 toggle
rrreee
에 속성을 추가해야 하는 경우 기본 모델인 경우 배열 또는 콜백 메서드를 withDefault
에 전달할 수 있습니다: rrreee다대다 연결
Attach/DetachEloquent는 또한 다음을 제공합니다. 몇 가지 추가 보조 방법을 사용하면 관련 모델을 더욱 편리하게 사용할 수 있습니다. 예를 들어, 사용자가 여러 역할을 가질 수 있고 각 역할을 여러 사용자가 공유할 수 있다고 가정해 보겠습니다. 사용자에게 역할을 추가하려면 중간 테이블에 레코드를 삽입해야 합니다. 이 작업은 attach
메서드를 사용하여 완료할 수 있습니다. 🎜rrreee🎜모델에 관계를 연결할 때 요구 사항 집합 중간 테이블에 삽입된 추가 데이터: 🎜rrreee🎜 물론 때로는 사용자 역할을 제거해야 하는 경우도 있습니다. 다대다 관련 레코드는 분리
를 사용하여 제거할 수 있습니다. detach
메소드는 중간 테이블에 해당하는 레코드를 제거하지만 다음 두 모델은 데이터베이스에 유지됩니다. 🎜rrreee🎜 편의상 attach
및 detach< /code>를 사용하면 ID 배열을 전달할 수도 있습니다. 🎜rrreee🎜🎜동기화 연결🎜🎜sync
메서드를 사용하여 빌드할 수도 있습니다. 다중 다대다 연관. sync
메소드는 ID 배열을 수신하여 중간 테이블의 레코드를 대체합니다. 중간 테이블 레코드 중 ID 배열에 없는 레코드는 모두 제거됩니다. 따라서 작업 후에는 지정된 배열의 ID만 중간 테이블에 유지됩니다. 🎜rrreee🎜 또한 ID별로 추가 추가 데이터를 중간 테이블에 전달할 수도 있습니다. 🎜rrreee🎜 기존 항목을 제거하지 않으려는 경우 ID, syncWithoutDetaching
메소드를 사용할 수 있습니다: 🎜rrreee🎜🎜Toggle 연관 🎜🎜다대다 연관도 제공 토글
지정된 ID 배열의 연결된 상태를 "토글"하는 데 사용되는 메서드입니다. 주어진 ID가 중간 테이블에 추가된 경우 제거됩니다. 마찬가지로 지정된 ID가 제거되면 추가됩니다. 🎜rrreee🎜🎜🎜중간 테이블에 저장 추가 데이터🎜🎜를 처리할 때 다대다 관계에서 save 메소드는 두 번째 매개변수로 추가 데이터 배열을 받습니다: 🎜rrreee🎜🎜중간 테이블 레코드 업데이트
중간 테이블의 기존 레코드를 업데이트해야 하는 경우 updateExistingPivot
를 사용할 수 있습니다. 이 메소드는 중간 테이블의 외래 키와 업데이트를 위해 업데이트할 데이터 배열을 수신합니다: updateExistingPivot
。此方法接收中间表的外键与要更新的数据数组进行更新:
rrreee更新父级时间戳
当一个模型属 belongsTo
或者 belongsToMany
另一个模型时, 例如 Comment
属于 Post
,有时更新子模型导致更新父模型时间戳非常有用。例如,当 Comment
模型被更新时,您要自动「触发」父级 Post
模型的 updated_at
时间戳的更新。Eloquent 让它变得简单。只要在子模型加一个包含关联名称的 touches
属性即可:
rrreee现在,当你更新一个 Comment
时,对应父级 Post
模型的 updated_at
字段同时也会被更新,使其更方便得知何时让一个 Post
rrreee
Comment
를 업데이트하면 해당 상위 Post code> 모델의 updated_at
필드도 업데이트되어 Post
모델의 캐시를 언제 무효화해야 하는지 더 쉽게 알 수 있습니다. 🎜rrreee🎜이 기사는 🎜에 처음 게재되었습니다. LearnKu.com🎜 웹사이트. 🎜🎜
rrreee🎜이제