Association modèle
- Particulier
- Définir l'association inverse
- Un-à-plusieurs (inverse)
- Modèle de relais personnalisé avec ID incrémentiel
- Relation un-à-un à distance
- Association un-à-plusieurs à distance
- Association polymorphe
- Un- à un (polymorphe)
- Structure de table
- Structure du modèle Un à plusieurs (polymorphe)
- Structure de table
- Obtenir une association
- Many-to-many (polymorphique)
- Structure de la table
- Structure du modèle
- Définir la relation d'association inverse
- Obtenir l'association
- Type de polymorphisme personnalisé
- Requête d'association
- Méthode d'association Vs. Attribut dynamique
- Requête d'association existante
- Requête d'association inexistante
- Nombre de modèles d'association
- pour le préchargement Ajouter des contraintes
- Préchargement
- Préchargement de plusieurs associations
- Préchargement imbriqué
- Préchargement des colonnes spécifiées
- Préchargement
- Insérer et mettre à jour le modèle associé "Méthode d'enregistrement"
- Association Plusieurs à Plusieurs
- Synchroniser l'association
- Basculer l'association
- Mettre à jour les enregistrements de la table intermédiaire
- Introduction
- Définition Association
- Association polymorphe
- Association de requête
- Ajouter des contraintes pour le préchargement
- Préchargement paresseux
- Insérer et mettre à jour les modèles associés
- Méthode
save code>
create
méthodesave
方法create
方法- 更新
Belongs To
Mettre à jour l'associationappartient à
- Association plusieurs à plusieurs
- Mettre à jour l'horodatage défini par les parents
- Un-à-plusieurs
- Enregistrer des données supplémentaires sur la table intermédiaire
- Mettre à jour l'horodatage des parents
Éloquent : Association
Définir les associations
Les associations éloquentes sont présentées sous forme de méthodes dans les classes modèles éloquentes. Comme le modèle Eloquent lui-même, les associations peuvent également être utilisées comme un puissant générateur d'instructions de requête, fournissant de puissantes fonctions d'appels en chaîne et de requête. Par exemple, nous pouvons attacher une contrainte à la chaîne d'appels à l'association 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'); }Mais avant de plonger dans l'utilisation des associations, apprenons comment définir chaque type d'association.
En tête-à-tête
Utilisateur
peut être associé à un modèle Téléphone
. Pour définir cette association, nous devons écrire une méthode phone
dans le modèle User
. Appelez la méthode hasOne
à l'intérieur de la méthode phone
et renvoyez son résultat : 🎜<?php namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model{ /** * 获取博客文章的评论 */ public function comments() { return $this->hasMany('App\Comment'); } }🎜 Le premier paramètre de la méthode
hasOne
est le nom de classe du modèle associé. Une fois l'association de modèle définie, nous pouvons utiliser les propriétés dynamiques d'Eloquent pour obtenir les enregistrements associés. Les propriétés dynamiques vous permettent d'accéder aux méthodes relationnelles tout comme les propriétés définies dans le modèle : 🎜$comments = App\Post::find(1)->comments;foreach ($comments as $comment) { //}🎜Eloquent déterminera le nom de la clé étrangère en fonction du nom du modèle. Dans ce cas, il est automatiquement supposé que le modèle
Phone
possède une clé étrangère user_id
. Si vous souhaitez remplacer cette convention, vous pouvez passer un deuxième paramètre à la méthode hasOne
: 🎜$comment = App\Post::find(1)->comments()->where('title', 'foo')->first();🎜 De plus, Eloquent suppose que la valeur de la clé étrangère est la même que la valeur de l'identifiant parent. (ou correspondance de colonne $primaryKey personnalisée). En d'autres termes, Eloquent recherchera une valeur dans la colonne user_id de l'enregistrement téléphonique qui correspond à la colonne id de la table Users. Si vous souhaitez que l'association utilise un nom de clé personnalisé autre que id, vous pouvez passer le troisième paramètre à la méthode hasOne : 🎜
return $this->hasMany('App\Comment', 'foreign_key'); return $this->hasMany('App\Comment', 'foreign_key', 'local_key');
Define reverse association
🎜Nous pouvons déjà accéder au modèleTéléphone
à partir du modèle Utilisateur
. Maintenant, définissons une autre association sur le modèle Téléphone
qui nous donnera accès au modèle Utilisateur
propriétaire du téléphone. Nous pouvons définir des associations inverses en utilisant la méthode belongsTo
correspondant à la méthode hasOne
: 🎜<?php namespace App; use Illuminate\Database\Eloquent\Model; class Comment extends Model{ /** * 获取此评论所属文章 */ public function post() { return $this->belongsTo('App\Post'); } }🎜Dans l'exemple ci-dessus, Eloquent tentera de faire correspondre
Téléphone
user_id
sur le modèle à id
sur le modèle User
. Il détermine le nom de clé étrangère par défaut en examinant le nom de la méthode de relation et en utilisant _id
comme suffixe. Cependant, si la clé étrangère du modèle Phone
n'est pas user_id
, alors un nom de clé personnalisé peut être transmis comme deuxième paramètre au belongsTo
. méthode : 🎜 $comment = App\Comment::find(1); echo $comment->post->title;🎜Si le modèle parent n'utilise pas
id
comme clé primaire, ou si vous souhaitez utiliser différents champs pour connecter les modèles enfants, vous pouvez passer le troisième paramètre au belongsTo Méthode
Spécifiez la clé personnalisée de la table de données parent sous la forme : 🎜/** * 获取此评论所属文章 */ public function post(){ return $this->belongsTo('App\Post', 'foreign_key'); }🎜🎜🎜🎜🎜🎜
Un-à-plusieurs
L'association "Un-à-plusieurs" est utilisée pour définir un modèle unique afin d'avoir un nombre quelconque d'autres modèles associés. Par exemple, un article de blog peut contenir un nombre infini de commentaires. Comme toutes les autres relations Eloquent, la définition d'une relation un-à-plusieurs consiste à écrire une méthode dans le modèle Eloquent :
/** * 获取此评论所属文章 */ public function post(){ return $this->belongsTo('App\Post', 'foreign_key', 'other_key'); }
N'oubliez pas qu'Eloquent déterminera automatiquement l'attribut de clé étrangère du modèle Comment
. Par convention, Eloquent utilisera la forme "snake case" du nom du modèle, plus le suffixe _id
comme champ de clé étrangère. Par conséquent, dans l'exemple ci-dessus, Eloquent supposera que la clé étrangère sur le Comment
correspondant au modèle Post
est 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
Comments
du modèle Post
. N'oubliez pas que, puisqu'Eloquent fournit des "propriétés dynamiques", nous pouvons accéder à la méthode de relation tout comme accéder aux propriétés du modèle : $user = App\User::find(1); foreach ($user->roles as $role) { echo $role->pivot->created_at; }Bien sûr, puisque toutes les relations peuvent également être utilisées comme constructeurs d'instructions de requête, vous pouvez utiliser la méthode des appels en chaîne, ajouter des contraintes sur la méthode
comments
: return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');Tout comme la méthode
hasOne
, vous pouvez également utiliser la méthode hasMany
Quand, remplacez l'utilisation par défaut de clés étrangères et clés locales en passant des paramètres supplémentaires : return $this->belongsToMany('App\Role')->withTimestamps();
hasMany
. Vous devez utiliser la méthode belongsTo
pour la définir dans le modèle enfant : 🎜return $this->belongsToMany('App\Podcast') ->as('subscription') ->withTimestamps();🎜Une fois cette relation définie, nous peut y accéder via l'"attribut dynamique"
post
du modèle Comment
pour obtenir le modèle Post
associé : 🎜$users = User::with('podcasts')->get(); foreach ($users->flatMap->podcasts as $podcast) { echo $podcast->subscription->created_at; }🎜Dans l'exemple ci-dessus, Eloquent essaiera Utilisez le
post_id
du modèle Comment
pour faire correspondre l'id
du modèle Post
. Le nom de la clé étrangère par défaut est déterminé par Eloquent en fonction du nom de l'association, suivi de _ et du nom du champ de clé primaire comme suffixe. Bien entendu, si la clé étrangère du modèle Comment
n'est pas post_id
, vous pouvez transmettre le nom de la clé personnalisée comme deuxième paramètre au belongsTo
. méthode : 🎜 return $this->belongsToMany('App\Role')->wherePivot('approved', 1); return $this->belongsToMany('App\Role')->wherePivotIn('priority', [1, 2]);🎜Si le modèle parent n'utilise pas
id
comme clé primaire, ou si vous souhaitez utiliser différents champs pour connecter les modèles enfants, vous pouvez passer le troisième paramètre au belongsTo Méthode
Spécifiez la clé personnalisée de la table de données parent sous la forme : 🎜<?php namespace App; use Illuminate\Database\Eloquent\Model; class Role extends Model{ /** * 拥有此角色的所有用户 */ public function users() { return $this->belongsToMany('App\User')->using('App\UserRole'); } }🎜🎜🎜🎜🎜🎜
Plusieurs-à-plusieurs
Les relations plusieurs-à-plusieurs sont légèrement plus complexes que les relations hasOne
et hasMany
. Par exemple, un utilisateur peut avoir plusieurs rôles, et ces rôles sont partagés par d’autres utilisateurs. Par exemple, de nombreux utilisateurs peuvent avoir le rôle « Administrateur ». Pour définir cette association, trois tables de base de données sont requises : users
, roles
et role_user
. La table role_user
est nommée par ordre alphabétique à partir des deux modèles associés et contient les champs user_id
et 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
. Par exemple, nous définissons la méthode roles
dans le User<. /code> modèle : countries
id - integer
name - string
users
id - integer
country_id - integer
name - string
posts
id - integer
user_id - integer
title - string
Une fois l'association définie, vous pouvez obtenir le rôle d'utilisateur grâce à l'attribut dynamique roles
: 🎜<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Country extends Model{
/**
* 当前国家所有文章。
*/
public function posts()
{
return $this->hasManyThrough('App\Post', 'App\User');
}
}
🎜Bien sûr, comme tous les autres modèles d'association, vous pouvez utiliser roles
Méthode, utilisez des appels en chaîne pour ajouter des contraintes à l'instruction de requête : 🎜class Country extends Model{
public function posts()
{
return $this->hasManyThrough(
'App\Post',
'App\User',
'country_id', // 用户表外键
'user_id', // 文章表外键
'id', // 国家表本地键
'id' // 用户表本地键
);
}
}
🎜Comme mentionné précédemment, afin de déterminer le nom de la table de connexion associée, Eloquent connectera les noms des deux modèles associés dans ordre alphabétique. Bien entendu, vous pouvez également ne pas utiliser cette convention et passer le deuxième paramètre à la méthode belongsToMany
: 🎜posts
id - integer
name - string
users
id - integer
name - string
images
id - integer
url - string
imageable_id - integer
imageable_type - string
🎜En plus de personnaliser le nom de la table de connexion, vous pouvez également passer des paramètres supplémentaires à < code>belongsToMany
pour définir le nom de clé du champ dans la table. Le troisième paramètre est le nom de clé étrangère du modèle qui définit cette association dans la table de connexion, et le quatrième paramètre est le nom de clé étrangère d'un autre modèle dans la table de connexion : 🎜<?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'); } }
Définir une association inverse
🎜Pour définir une association inverse plusieurs-à-plusieurs, il suffit d'appeler la méthodebelongsToMany
dans le modèle d'association. Nous définissons la méthode users
dans le modèle Role
: 🎜$post = App\Post::find(1); $image = $post->image;🎜Comme vous pouvez le voir, à l'exception de l'introduction du modèle
AppUser
, tout le reste est le même que dans >Utilisateur
est exactement le même que celui défini dans le modèle. Puisque nous réutilisons la méthode belongsToMany
, le nom de la table de jointure personnalisée et le nom du champ de la clé dans la table de jointure personnalisée s'appliquent également ici. 🎜🎜🎜Obtenir des champs de table intermédiaires
Comme vous venez de l'apprendre, les relations plusieurs-à-plusieurs nécessitent une table intermédiaire pour fournir un support. Eloquent fournit des méthodes utiles pour interagir avec cette table. Par exemple, supposons que notre objet User
soit associé à plusieurs objets Role
. Après avoir obtenu ces objets associés, vous pouvez utiliser l'attribut pivot
du modèle pour accéder aux données de la table intermédiaire : 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 - stringA noter que chaque objet du modèle
Rôle
que nous obtenons, se voient automatiquement attribuer l'attribut pivot
, qui représente un objet modèle de la table intermédiaire et peut être utilisé comme les autres modèles Eloquent. <?php namespace App; use Illuminate\Database\Eloquent\Model; class Post extends Model{ /** * 获取文章的所有标签。 */ public function tags() { return $this->morphToMany('App\Tag', 'taggable'); } }Si vous souhaitez que la table intermédiaire conserve automatiquement les horodatages
created_at
et updated_at
, ajoutez la méthode withTimestamps
lors de la définition de l'association : <?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'); } }🎜Personnalisez le nom de l'attribut
pivot
🎜🎜Comme mentionné précédemment, les attributs de la table intermédiaire sont accessibles à l'aide du pivot< /code> attribut . Vous êtes cependant libre de personnaliser le nom de cette propriété pour mieux refléter son utilisation dans votre application. 🎜🎜Par exemple, si votre application contient des utilisateurs susceptibles de s'abonner, il peut exister une relation plusieurs-à-plusieurs entre les utilisateurs et les blogs. Si tel est le cas, vous souhaiterez peut-être nommer l'accesseur de table intermédiaire abonnement
au lieu de pivot
. Cela peut être fait en utilisant la méthode as
lors de la définition de la relation : 🎜$post = App\Post::find(1);foreach ($post->tags as $tag) {
//
}
🎜Une fois définie, vous pouvez accéder aux données de la table intermédiaire en utilisant un nom personnalisé : 🎜$tag = App\Tag::find(1);foreach ($tag->videos as $video) {
//
}
🎜🎜Filtrer les relations via des tables intermédiaires🎜🎜Lors de la définition des relations, vous pouvez également utiliser les méthodes wherePivot
et wherePivotIn
pour filtrer belongsToMany
renvoie les résultats pour : 🎜use Illuminate\Database\Eloquent\Relations\Relation;
Relation::morphMap([
'posts' => 'App\Post',
'videos' => 'App\Video',
]);
🎜🎜🎜🎜🎜🎜Définir un modèle de table intermédiaire
Définir un modèle de table intermédiaire personnalisé
Si vous souhaitez définir un modèle personnalisé pour représenter la table intermédiaire dans la relation d'association, vous pouvez appeler la méthode using
lors de la définition de l'association. Les modèles de table intermédiaire Plusieurs-à-plusieurs
personnalisés doivent s'étendre à partir de la classe IlluminateDatabaseEloquentRelationsPivot, et les modèles de table intermédiaire personnalisés Plusieurs-à-plusieurs (polymorphes)
doivent hériter de la classe IlluminateDatabaseEloquentRelationsMorphPivot. Par exemple, 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
Lorsque nous écrivons l'association du modèle de rôle, nous utilisons le modèle de table intermédiaire personnalisé 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();
Lors de la définition du modèle UserRole
, nous devons étendre < code>Pivot< /code> Classe : $posts = App\Post::doesntHave('comments')->get();
Vous pouvez utiliser une combinaison de using
et withPivot
pour récupérer les colonnes d'une table intermédiaire. Par exemple, created_by
et updated_by
peuvent être récupérés de la table intermédiaire UserRole
en passant le nom de la colonne au withPivot
méthode. > Deux colonnes de données.
use Illuminate\Database\Eloquent\Builder;
$posts = App\Post::whereDoesntHave('comments', function (Builder $query)
{
$query->where('content', 'like', 'foo%');
})->get();
Modèle de relais personnalisé avec ID croissant
Si vous définissez plusieurs paires avec un modèle de relais personnalisé, plusieurs relations et que le modèle de relais a une clé primaire à incrémentation automatique, vous devez vous assurer que la classe de modèle de relais personnalisé définit un attribut incrementing
avec une valeur de true
:🎜use Illuminate\Database\Eloquent\Builder;
$posts = App\Post::whereDoesntHave('comments.author', function (Builder $query)
{
$query->where('banned', 1);
})->get();
🎜🎜🎜🎜🎜Relation individuelle à distance🎜🎜Association individuelle à distance via la mise en œuvre d'un modèle d'association intermédiaire. 🎜Par exemple, si chaque fournisseur a un utilisateur et que chaque utilisateur est associé à un historique utilisateur, alors le fournisseur peut accéder à l'historique de l'utilisateur via l'utilisateur, regardons les tables de base de données requises pour définir cette relation : 🎜$posts = App\Post::withCount('comments')->get();
foreach ($posts as $post) {
echo $post->comments_count;
}
🎜Bien que le La table history
ne contient pas supplier_id
, la relation hasOneThrough
peut donner accès à l'historique de l'utilisateur pour accéder au modèle fournisseur. Maintenant que nous avons inspecté la structure tabulaire de la relation, définissons la méthode correspondante sur le modèle Supplier
: 🎜$posts = App\Post::withCount(['votes', 'comments' => function ($query)
{
$query->where('content', 'like', 'foo%');
}])->get();
echo $posts[0]->votes_count;echo $posts[0]->comments_count;
🎜Le premier paramètre passé à la méthode hasOneThrough
est le souhaité accès Le nom du modèle, le deuxième paramètre est le nom du modèle intermédiaire. 🎜🎜Lors de l'exécution de requêtes associées, les noms de clés étrangères conventionnelles d'Eloquent sont généralement utilisés. Si vous souhaitez personnaliser la clé associée, vous pouvez le faire en passant les troisième et quatrième paramètres à la méthode hasOneThrough
. Le troisième paramètre représente le nom de la clé étrangère du modèle intermédiaire et le quatrième paramètre le représente. Le nom de clé étrangère du modèle final. Le cinquième paramètre représente le nom de la clé locale, tandis que le sixième paramètre représente le nom de la clé locale du modèle intermédiaire : 🎜$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;
🎜🎜🎜🎜🎜🎜Association un-à-plusieurs à distance
L'association un-à-plusieurs à distance offre un moyen pratique et court d'obtenir des associations à distance via des associations intermédiaires. Par exemple, un modèle Pays
peut avoir plusieurs modèles Post
via un modèle Utilisateur
intermédiaire. Dans cet exemple, vous pouvez facilement collecter tous les articles de blog d'un pays donné. Jetons un coup d'œil aux tables de données nécessaires pour définir cette association : Country
模型可以通过中间的 User
模型获得多个 Post
模型。在这个例子中,你可以轻易地收集给定国家的所有博客文章。让我们来看看定义这种关联所需的数据表:
$query = App\Post::select(['title', 'body'])->withCount('comments');
echo $posts[0]->title;
echo $posts[0]->body;
echo $posts[0]->comments_count;
虽然 posts
表中不包含 country_id
字段,但 hasManyThrough
关联能让我们通过 $country->posts
访问到一个国家下所有的用户文章。为了完成这个查询,Eloquent 会先检查中间表 users
的 country_id
字段,找到所有匹配的用户 ID 后,使用这些 ID,在 posts
表中完成查找。
现在,我们已经知道了定义这种关联所需的数据表结构,接下来,让我们在 Country
模型中定义它:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Book extends Model{
/**
* 获取书籍作者。
*/
public function author()
{
return $this->belongsTo('App\Author');
}
}
hasManyThrough
方法的第一个参数是我们最终希望访问的模型名称,而第二个参数是中间模型的名称。
当执行关联查询时,通常会使用 Eloquent 约定的外键名。如果你想要自定义关联的键,可以通过给 hasManyThrough
方法传递第三个和第四个参数实现,第三个参数表示中间模型的外键名,第四个参数表示最终模型的外键名。第五个参数表示本地键名,而第六个参数表示中间模型的本地键名:
$books = App\Book::all();
foreach ($books as $book)
{
echo $book->author->name;
}
多态关联
多态关联允许目标模型借助单个关联从属于多个模型。
一对一(多态)
表结构
一对一多态关联与简单的一对一关联类似;不过,目标模型能够在一个关联上从属于多个模型。例如,博客 Post
和 User
可能共享一个关联到 Image
模型的关系。使用一对一多态关联允许使用一个唯一图片列表同时用于博客文章和用户账户。让我们先看看表结构:
$books = App\Book::with('author')->get();
foreach ($books as $book) {
echo $book->author->name;
}
要特别留意 images
表的 imageable_id
和 imageable_type
列。 imageable_id
列包含文章或用户的 ID 值,而 imageable_type
列包含的则是父模型的类名。Eloquent 在访问 imageable
时使用 imageable_type
select * from books
select * from authors where id in (1, 2, 3, 4, 5, ...)
Bien que la table posts
ne contienne pas de champ country_id
, hasManyThrough
L'association nous permet d'accéder à toutes les publications des utilisateurs d'un pays via $country->posts
. Afin de compléter cette requête, Eloquent vérifiera d'abord le champ country_id
de la table intermédiaire users
. Après avoir trouvé tous les ID utilisateur correspondants, utilisez ces ID pour publier dans . posts
Complétez la recherche dans le tableau. Maintenant que nous connaissons la structure de table de données nécessaire pour définir cette association, définissons-la dans le modèle Country
: $books = App\Book::with(['author', 'publisher'])->get();
Méthode hasManyThrough
Le premier paramètre est le nom de le modèle auquel nous souhaitons finalement accéder, tandis que le deuxième paramètre est le nom du modèle intermédiaire. Lors de l'exécution de requêtes associées, les noms de clés étrangères conventionnelles d'Eloquent sont généralement utilisés. Si vous souhaitez personnaliser la clé associée, vous pouvez le faire en passant les troisième et quatrième paramètres à la méthode hasManyThrough
. Le troisième paramètre représente le nom de la clé étrangère du modèle intermédiaire et le quatrième paramètre le représente. Le nom de clé étrangère du modèle final. Le cinquième paramètre représente le nom de la clé locale, tandis que le sixième paramètre représente le nom de la clé locale du modèle intermédiaire : $books = App\Book::with('author.contacts')->get();
🎜🎜Associations polymorphes
🎜Les associations polymorphes permettent à un modèle cible d'être subordonné à plusieurs modèles avec une seule association. 🎜🎜🎜🎜🎜One-to-one (polymorphique)🎜< div name="03a0d2" data-unique="03a0d2">🎜🎜Structure de la table🎜🎜L'association polymorphe un-à-un est similaire à une simple association un-à-un, cependant, le modèle cible peut appartenir à plusieurs modèles sur ; une seule association. Par exemple, les blogs Post
et User
peuvent partager une relation avec le modèle Image
. L'utilisation d'une association polymorphe un-à-un permet d'utiliser une liste unique d'images pour les articles de blog et les comptes d'utilisateurs. Jetons d'abord un coup d'œil à la structure de la table : 🎜$users = App\Book::with('author:id,name')->get();
🎜Portez une attention particulière aux colonnes imageable_id
et imageable_type
de la table images
. La colonne imageable_id
contient la valeur de la publication ou de l'ID utilisateur, tandis que la colonne imageable_type
contient le nom de classe du modèle parent. Eloquent utilise la colonne imageable_type
pour déterminer le "type" du modèle parent lors de l'accès à imageable
. 🎜🎜🎜🎜Structure du modèle🎜🎜Ensuite, regardons la définition du modèle pour établir l'association : 🎜$users = App\User::with(['posts' => function ($query) {
$query->where('title', 'like', '%first%');
}])->get();
🎜🎜Obtenir l'association
Une fois la table et le modèle définis, cette association est accessible via le modèle. Par exemple, pour obtenir l'image de l'article, vous pouvez utiliser l'attribut dynamique image
: image
动态属性:
$users = App\User::with(['posts' => function ($query) {
$query->orderBy('created_at', 'desc');
}])->get();
还可以通过访问执行 morphTo
调用的方法名来从多态模型中获知父模型。在这个例子中,就是 Image
模型的 imageable
方法。所以,我们可以像动态属性那样访问这个方法:
$books = App\Book::all();
if ($someCondition) {
$books->load('author', 'publisher');
}
Image
模型的 imageable
关联将返回 Post
或 User
实例,其结果取决于图片属性哪个模型。
一对多(多态)
表结构
一对多多态关联与简单的一对多关联类似;不过,目标模型可以在一个关联中从属于多个模型。假设应用中的用户可以同时 「评论」 文章和视频。使用多态关联,可以用单个 comments
表同时满足这些情况。我们还是先来看看用来构建这种关联的表结构:
$books->load(['author' => function ($query) {
$query->orderBy('published_date', 'asc');
}]);
模型结构
接下来,看看构建这种关联的模型定义:
public function format(Book $book){
$book->loadMissing('author');
return [
'name' => $book->name,
'author' => $book->author->name
];
}
获取关联
一旦定义了数据库表和模型,就可以通过模型访问关联。例如,可以使用 comments
动态属性访问文章的全部评论:
<?php
use Illuminate\Database\Eloquent\Model;
class ActivityFeed extends Model{
/**
* Get the parent of the activity feed record.
*/
public function parentable()
{
return $this->morphTo();
}
}
还可以通过访问执行 morphTo
调用的方法名来从多态模型获取其所属模型。在本例中,就是 Comment
模型的 commentable
方法:
$activities = ActivityFeed::with('parentable')
->get()
->loadMorph('parentable', [
Event::class => ['calendar'],
Photo::class => ['tags'],
Post::class => ['author'],
]);
Comment
模型的 commentable
关联将返回 Post
或 Video
实例,其结果取决于评论所属的模型。
多对多(多态)
表结构
多对多多态关联比 morphOne
和 morphMany
关联略微复杂一些。例如,博客 Post
和 Video
模型能够共享关联到 Tag
模型的多态关系。使用多对多多态关联允许使用一个唯一标签在博客文章和视频间共享。以下是多对多多态关联的表结构:
$comment = new App\Comment(['message' => 'A new comment.']);
$post = App\Post::find(1);
$post->comments()->save($comment);
模型结构
接下来,在模型上定义关联。Post
和 Video
模型都有调用 Eloquent 基类上 morphToMany
方法的 tags
$post = App\Post::find(1);
$post->comments()->saveMany([
new App\Comment(['message' => 'A new comment.']),
new App\Comment(['message' => 'Another comment.']),
]);
Vous pouvez également obtenir le modèle parent à partir du modèle polymorphe en accédant au nom de la méthode qui exécute le morphTo
appel. Dans ce cas, il s'agit de la méthode imageable
du modèle Image
. Ainsi, on peut accéder à cette méthode comme une propriété dynamique : $post = App\Post::find(1);
$post->comments[0]->message = 'Message';
$post->comments[0]->author->name = 'Author Name';$post->push();
Image
L'association imageable
du modèle renverra soit Post
soit User < /code> instance, le résultat dépend du modèle auquel appartient l'attribut d'image. 🎜🎜🎜🎜Un à plusieurs (polymorphe) < /h3>🎜🎜Structure de table🎜🎜Les associations polymorphes un-à-plusieurs sont similaires aux associations un-à-plusieurs simples, cependant, le modèle cible peut être ; subordonnés à plusieurs dans un modèle d’association. Supposons que les utilisateurs de l’application puissent « commenter » des articles et des vidéos en même temps. En utilisant des associations polymorphes, vous pouvez satisfaire ces deux situations avec une seule table comments
. Jetons d'abord un coup d'œil à la structure de table utilisée pour construire cette association : 🎜$post = App\Post::find(1);
$comment = $post->comments()->create([
'message' => 'A new comment.',
]);
🎜🎜Structure du modèle🎜🎜Ensuite, regardons le modèle qui construit cette association Définition : 🎜$post = App\Post::find(1);$post->comments()->createMany([
[
'message' => 'A new comment.',
],
[
'message' => 'Another new comment.',
],
]);
🎜🎜Obtenir l'association 🎜🎜Une fois la table et le modèle de la base de données définis, l'association est accessible via le modèle. Par exemple, vous pouvez accéder à tous les commentaires d'un article en utilisant l'attribut dynamique comments
: 🎜$account = App\Account::find(10);
$user->account()->associate($account);$user->save();
🎜 Vous pouvez également récupérer le modèle auquel il appartient à partir du modèle polymorphe en accédant au nom de la méthode qui effectue le Appel morphTo
. Dans ce cas, la méthode commentable
du modèle Comment
: 🎜$user->account()->dissociate();$user->save();
🎜 L'association commentable
du modèle Comment
renverra Post
ou Vidéo
, le résultat dépend du modèle auquel appartient le commentaire. 🎜🎜🎜🎜Plusieurs à plusieurs (polymorphes) < /h3>🎜🎜Structure de table🎜🎜L'association polymorphe plusieurs à plusieurs est légèrement plus complexe que morphOne
et morphMany
association Certains. Par exemple, les modèles Blog Post
et Vidéo
peuvent partager une relation polymorphe avec le modèle Tag
. L'utilisation d'une association polymorphe plusieurs-à-plusieurs permet le partage entre des articles de blog et des vidéos à l'aide d'une balise unique. Voici la structure de table d'une association polymorphe plusieurs-à-plusieurs : 🎜/**
* 获取帖子的作者。
*/
public function user(){
return $this->belongsTo('App\User')->withDefault();
}
🎜🎜Structure du modèle🎜🎜Ensuite, définissez l'association sur le modèle. Les modèles Post
et Video
ont des méthodes tags
qui appellent la méthode morphToMany
sur la classe de base Eloquent : 🎜/**
* 获取帖子的作者。
*/
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';
});
}
🎜🎜Définissez la relation d'association inverse
Ensuite, vous devez définir une méthode pour chaque modèle d'association sur le modèle Tag
. Dans cet exemple, nous définirons la méthode posts
et la méthode videos
: Tag
模型上为每个关联模型定义一个方法。在这个示例中,我们将会定义 posts
方法和 videos
方法:
$user = App\User::find(1);
$user->roles()->attach($roleId);
获取关联
一旦定义了数据库表和模型,就可以通过模型访问关联。例如,可以使用 tags
动态属性访问文章的所有标签:
$user->roles()->attach($roleId, ['expires' => $expires]);
还可以访问执行 morphedByMany
方法调用的方法名来从多态模型获取其所属模型。在这个示例中,就是 Tag
模型的 posts
或 videos
方法。可以像动态属性一样访问这些方法:
// 移除用户的一个角色...
$user->roles()->detach($roleId);
// 移除用户的所有角色...
$user->roles()->detach();
自定义多态类型
默认情况下, Laravel 使用完全限定类名存储关联模型类型。在上面的一对多示例中, 因为 Comment
可能从属于一个 Post
或一个 Video
,默认的 commentable_type
就将分别是 AppPost
或 AppVideo
。不过,你可能希望数据库与应用的内部结构解耦。在这种情况下,可以定义一个 「morph 映射」 来通知 Eloquent 使用自定义名称代替对应的类名:
$user = App\User::find(1);
$user->roles()->detach([1, 2, 3]);
$user->roles()->attach([
1 => ['expires' => $expires],
2 => ['expires' => $expires]
]);
可以在 AppServiceProvider
的 boot
函数中注册 morphMap
,或者创建一个单独的服务提供者。
查询关联
由于 Eloquent 关联的所有类型都通过方法定义,你可以调用这些方法,而无需真实执行关联查询。另外,所有 Eloquent 关联类型用作 查询构造器,允许你在数据库上执行 SQL 之前,持续通过链式调用添加约束。
例如,假设一个博客系统的 User
模型有许多关联的 Post
模型:
$user->roles()->sync([1, 2, 3]);
你可以查询 posts
$user->roles()->sync([1 => ['expires' => true], 2, 3]);
Obtenir le association
Une fois la table de base de données et le modèle définis, les relations sont accessibles via le modèle. Par exemple, vous pouvez utiliser l'attribut dynamique tags
pour accéder à toutes les balises d'un article : $user->roles()->syncWithoutDetaching([1, 2, 3]);
Vous pouvez également accéder au nom de la méthode qui exécute l'appel de la méthode morphedByMany
pour obtenir le modèle auquel il appartient à partir du modèle polymorphe. Dans cet exemple, il s'agit de la méthode posts
ou videos
du modèle Tag
. Ces méthodes sont accessibles comme des propriétés dynamiques :
$user->roles()->toggle([1, 2, 3]);
🎜🎜Types polymorphes personnalisés h3>🎜Par défaut, Laravel stocke les types de modèles associés en utilisant des noms de classe complets. Dans l'exemple un-à-plusieurs ci-dessus, puisque Comment
peut appartenir à un Post
ou à une Vidéo
, le commentable_type
par défaut code > sera respectivement AppPost
ou AppVideo
. Cependant, vous souhaiterez peut-être dissocier la base de données de la structure interne de votre application. Dans ce cas, vous pouvez définir un "morph mapping" pour indiquer à Eloquent d'utiliser un nom personnalisé au lieu du nom de classe correspondant : 🎜App\User::find(1)->roles()->save($role, ['expires' => $expires]);
🎜Peut être effectué dans la fonction boot
de AppServiceProvider< /code> Enregistrez morphMap
ou créez un fournisseur de services distinct. 🎜🎜🎜🎜🎜Interroger les relations
🎜Puisque tous les types de relations éloquentes sont définis via des méthodes , vous pouvez appeler ces méthodes sans exécuter réellement la requête associée. De plus, tous les types de relations Eloquent agissent comme des générateurs de requêtes, vous permettant d'ajouter en continu des contraintes via une chaîne d'appels avant d'exécuter SQL sur la base de données. 🎜🎜Par exemple, supposons que le modèle Utilisateur
d'un système de blog ait de nombreux modèles Post
associés : 🎜$user = App\User::find(1);
$user->roles()->updateExistingPivot($roleId, $attributes);
🎜Vous pouvez interroger l'association posts
et la fournir ajoute des contraintes supplémentaires : 🎜<?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');
}
}
🎜 Vous pouvez utiliser n'importe quelle méthode de création de requêtes sur l'association, veuillez consulter la documentation du générateur de requêtes pour savoir quelles méthodes peuvent vous être utiles. 🎜🎜🎜🎜🎜🎜🎜 Méthodes de relation et propriétés dynamiques
Si vous n'avez pas besoin d'ajouter des contraintes supplémentaires à votre requête de relation Eloquent, vous pouvez accéder à la relation comme une propriété. Par exemple, en continuant à utiliser les exemples de modèles User
et Post
, vous pouvez accéder à toutes les publications d'un utilisateur comme ceci : User
和 Post
示例模型,可以这样访问用户的全部文章:
$comment = App\Comment::find(1);
$comment->text = 'Edit to this comment!';
$comment->save();
动态属性是「懒加载」的,这意味着它们仅在你真实访问关联数据时才被载入。因此,开发者经常使用 预加载 预先加载那些他们确知在载入模型后将访问的关联。对载入模型关联中必定被执行的 SQL 查询而言,预加载显著减少了查询的执行次数。
查询已存在的关联
在访问模型记录时,可能希望基于关联的存在限制查询结果。比如想要获取至少存在一条评论的所有文章,可以通过给 has
和 orHas
方法传递关联名称来实现:
rrreee还可以指定运算符和数量进一步自定义查询:
rrreee还可以用 「点」语法构造嵌套的 has
语句。比如,可以获取拥有至少一条评论和投票的文章:
rrreee如果需要更多功能,可以使用 whereHas
和 orWhereHas
方法将「where」 条件放到 has
查询上。这些方法允许你向关联加入自定义约束,比如检查评论内容:
rrreee查询不存在的关联
在访问模型记录时,可能希望基于关联不存在来限制查询结果。假设想要获取不存在任何评论的文章,可以通过向 doesntHave
和 orDoesntHave
方法传递关联名称来实现:
rrreee如果需要更多功能,可以使用 whereDoesntHave
和 orWhereDoesntHave
方法将「where」 条件加到 doesntHave
rrreee
Les propriétés dynamiques sont "chargées paresseusement", ce qui signifie qu'ils ne sont chargés que lorsque les données associées sont chargées uniquement lorsque vous y accédez réellement. Par conséquent, les développeurs utilisent souvent eager-loading pour précharger les relations auxquelles ils savent qu'ils accéderont après le chargement du modèle. Pour les requêtes SQL qui doivent être exécutées lors du chargement des associations de modèles, le chargement rapide réduit considérablement le nombre d'exécutions de requêtes.
Interroger les relations existantes🎜Lorsque vous accédez aux enregistrements de modèle, vous souhaiterez peut-être vous baser sur les relation L'existence de limite les résultats de la requête. Par exemple, si vous souhaitez récupérer tous les articles avec au moins un commentaire, vous pouvez passer le nom de l'association aux méthodes has
et orHas
: 🎜rrreee🎜Vous pouvez également spécifier l'opérateur et la quantité pour approfondir la requête personnalisée : 🎜rrreee🎜 Vous pouvez également utiliser la syntaxe "point" pour construire des instructions has
imbriquées. Par exemple, vous pouvez obtenir des articles avec au moins un commentaire et voter : 🎜rrreee🎜Si vous avez besoin de plus de fonctions, vous pouvez utiliser les méthodes whereHas
et orWhereHas
pour mettre le " où" condition dans la requête < code>has. Ces méthodes vous permettent d'ajouter des contraintes personnalisées à la relation, comme vérifier le contenu du commentaire : 🎜rrreee🎜🎜🎜🎜🎜 Requête de relations inexistantes🎜🎜Lors de l'accès aux enregistrements de modèle, vous souhaiterez peut-être limiter les résultats de la requête en fonction de la non-existence de la relation. Supposons que vous souhaitiez obtenir des articles qui n'ont aucun commentaire. Vous pouvez le faire en passant le nom de l'association aux méthodes doesntHave
et orDoesntHave
: 🎜 rrreee🎜Si nécessaire Pour plus de fonctionnalités, vous pouvez utiliser les méthodes whereDoesntHave
et orWhereDoesntHave
pour ajouter des conditions "where" à la requête doesntHave
. Ces méthodes vous permettent d'ajouter des restrictions personnalisées à l'association, comme la détection du contenu des commentaires : 🎜rrreee🎜Vous pouvez également utiliser la syntaxe "point" pour effectuer des requêtes d'association imbriquées. Par exemple, la requête suivante est utilisée pour obtenir des articles avec des commentaires d'auteurs qui n'ont pas été bannis : 🎜rrreee🎜🎜🎜🎜🎜🎜Nombre de modèles relationnels
Si vous souhaitez calculer uniquement le nombre statistique de résultats d'association sans les charger réellement, vous pouvez utiliser la méthode withCount
, qui sera placée dans le {relation}_count < de la colonne /code> du modèle de résultat. Un exemple est le suivant : 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
Vous pouvez ajouter des "comptes" à plusieurs relations, tout comme vous ajoutez des contraintes aux requêtes :
rrreee Vous pouvez également alias les résultats du nombre de relations, ce qui vous permet d'ajouter plusieurs comptes sur la même relation : rrreeeSi vous souhaitez assembler les requêtes withCount
et select
ensemble, assurez-vous d'appeler withCount
après la méthode select
:
rrreee< a name="eager-loading">🎜🎜Eager-loading
🎜Lors de l'accès à l'association Eloquent en tant qu'attribut , les données associées sont un "chargement paresseux". De cette façon, les données associées ne seront réellement chargées qu’au premier accès à la propriété. Cependant, Eloquent peut « précharger » les relations enfants lors de l'interrogation du modèle parent. Un chargement rapide peut atténuer le problème des requêtes N+1. Pour illustrer le problème de requête N + 1, considérons le cas où le modèle Livre
est associé à Auteur
: 🎜rrreee🎜Maintenant, récupérons tous les livres et leurs auteurs : 🎜 rrreee🎜This La boucle exécutera une requête pour obtenir tous les livres, puis pour chaque livre, exécutera une requête pour obtenir l'auteur. Si nous avons 25 livres, cette boucle exécutera 26 requêtes : 1 pour interroger le livre, et 25 requêtes supplémentaires pour interroger l'auteur de chaque livre. 🎜🎜Heureusement, nous avons pu condenser l'opération à seulement 2 requêtes grâce au chargement rapide. Au moment de la requête, vous pouvez utiliser la méthode with
pour spécifier l'association que vous souhaitez précharger : 🎜rrreee🎜Dans cet exemple, seules deux requêtes ont été exécutées : 🎜rrreee🎜Précharger plusieurs associations
🎜Parfois, vous devrez peut-être précharger plusieurs associations différentes en une seule opération. Pour y parvenir, il suffit de passer un paramètre de tableau composé de plusieurs noms associés à la méthode with
: 🎜rrreee🎜Chargement du préréglage imbriqué
🎜Vous pouvez utiliser la syntaxe "point" pour précharger les associations imbriquées. Par exemple, précharger tous les auteurs de livres et leurs coordonnées dans une seule déclaration éloquente : 🎜rrreee🎜Précharger les colonnes spécifiées
🎜 n'est pas toujours nécessaire. chaque colonne de la relation. Dans ce cas, Eloquent vous permet de spécifier les colonnes que vous souhaitez obtenir pour l'association : 🎜rrreee🎜{note} Lorsque vous utilisez cette fonctionnalité, assurez-vous d'inclure id dans la liste des colonnes à obtenir .code> colonne. 🎜🎜🎜🎜🎜🎜🎜🎜Ajout de contraintes pour le préchargement
Parfois, vous souhaiterez peut-être précharger une relation tout en ajoutant des conditions de requête supplémentaires à la requête de préchargement, comme dans l'exemple suivant :
rrreeeDans cet exemple, Eloquent ne préchargera que les articles dont le titre< La colonne /code> contient le mot-clé first
. Vous pouvez également appeler d'autres méthodes de création de requêtes pour personnaliser davantage l'opération de préchargement : 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} Lorsque vous contraignez le préchargement, vous ne pouvez pas utiliser limit
et take
Générateur de requêtes méthode.
PréchargementPeut-être souhaitez-vous aussi terminer le chargement du modèle. Ensuite effectuer un chargement rapide. Par exemple, si vous souhaitez charger dynamiquement des données associées, alors la méthode load
vous sera très utile : Lorsque l'association n'est pas chargée, vous pouvez utiliser la méthode loadMissing
: rrreeeChargement paresseux imbriqué& morphTo< /code>
🎜Si vous souhaitez charger rapidement la relation morphTo
, ainsi que les relations imbriquées sur diverses entités que la relation peut renvoyer, vous pouvez utiliser loadMorph
méthode. 🎜🎜Cette méthode accepte le nom de la relation morphTo
comme premier paramètre, et le deuxième paramètre reçoit un tableau de modèles et un tableau de relations. Pour illustrer cette approche, jetez un œil à l'exemple de modèle suivant : 🎜rrreee🎜Dans cet exemple, supposons Event
, Photo
et Post
Les modèles peuvent créer des modèles ActivityFeed
. De plus, supposons que le modèle Evénement
appartient au modèle Calendrier
, le modèle Photo
est associé au modèle Tag
, et Le modèle Post
appartient au modèle Auteur
. 🎜🎜En utilisant ces définitions et relations de modèle, nous pouvons récupérer l'instance de modèle ActivityFeed
et charger tous les modèles parentables
et leurs relations imbriquées respectives en même temps : 🎜rrreee🎜🎜🎜🎜 🎜 🎜🎜Insérer et mettre à jour les modèles associés🎜🎜🎜🎜🎜🎜🎜Méthode de sauvegarde
Eloquent fournit un moyen pratique d'ajouter des associations à de nouveaux modèles. Par exemple, vous devrez peut-être ajouter un nouveau Commentaire
à un modèle Post
. Vous n'avez pas besoin de définir manuellement l'attribut post_id
dans Comment
, vous pouvez directement utiliser la méthode save
du modèle associé pour enregistrer le Commenter
directement. Insérer : 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
Il est à noter que nous n'utilisons pas d'attributs dynamiques pour accéder à l'association comments
. Au lieu de cela, nous appelons la méthode comments
pour obtenir l'instance associée. La méthode save
ajoutera automatiquement la valeur post_id
appropriée au modèle Comment
. Si vous devez enregistrer plusieurs modèles associés, vous pouvez utiliser la méthode saveMany
: rrreee
🎜Enregistrer de manière récursive les modèles et les données associées
🎜Si vous souhaitez enregistrer
votre modèle et toutes ses données associées, vous pouvez utiliser push< /code> Méthode :🎜rrreee🎜🎜🎜🎜🎜Nouvelle méthode🎜🎜Sauf save En plus des méthodes code> et saveMany
, vous pouvez également utiliser la méthode create
. Il accepte un tableau de propriétés, crée un modèle et l'insère dans la base de données. De plus, la différence entre la méthode save
et la méthode create
est que la méthode save
accepte une instance complète du modèle Eloquent, tandis que la méthode create
accepte les tableaux PHP ordinaires : 🎜rrreee🎜{tip} Avant d'utiliser la méthode create
, assurez-vous de consulter le chapitre sur l'affectation par lots de ce document. 🎜
🎜Vous pouvez également utiliser la méthode createMany
pour créer plusieurs modèles associés : 🎜rrreee🎜Vous pouvez également utiliser findOrNew
, firstOrNew
, les méthodes firstOrCreate
et updateOrCreate
pour créer et mettre à jour des modèles de relations.🎜🎜🎜🎜🎜🎜Mettre à jour l'association belongsTo
🎜🎜Lors de la mise à jour de l'association belongsTo
, vous pouvez utiliser la méthode associate
. Cette méthode définira la clé étrangère dans le modèle enfant : 🎜rrreee🎜Lors de la suppression de l'association belongsTo
, vous pouvez utiliser la méthode dissociate
. Cette méthode définira la clé étrangère associée sur null
:🎜rrreee🎜🎜🎜🎜🎜🎜Modèle par défaut
La relation belongsTo
vous permet de spécifier un modèle par défaut. Lorsque la relation donnée est nulle
, le modèle par défaut sera renvoyé. Ce modèle est appelé Modèle d'objet nul et peut réduire les vérifications inutiles dans votre code. Dans l'exemple ci-dessous, si l'auteur de la publication publiée n'est pas trouvé, la relation user
renverra un modèle AppUser
vide : 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
Si vous devez ajouter des attributs à le modèle par défaut, vous pouvez passer un tableau ou une méthode de rappel à withDefault
: rrreeeAssociation plusieurs-à-plusieurs
Attach/DetachEloquent fournit également quelques méthodes auxiliaires supplémentaires, rendant l'utilisation des modèles associés plus pratique. Par exemple, supposons qu'un utilisateur puisse avoir plusieurs rôles et que chaque rôle puisse être partagé par plusieurs utilisateurs. L'attachement d'un rôle à un utilisateur s'effectue en insérant un enregistrement dans la table intermédiaire. Cette opération peut être réalisée à l'aide de la méthode attach
: 🎜rrreee🎜Lors de l'attachement d'une relation à un modèle, vous pouvez également transmettre un rôle. ensemble d'exigences Données supplémentaires insérées dans le tableau intermédiaire : 🎜rrreee🎜 Bien sûr, il est parfois également nécessaire de supprimer le rôle de l'utilisateur. Plusieurs enregistrements associés peuvent être supprimés à l'aide de detach
. La méthode detach
supprimera les enregistrements correspondant à la table intermédiaire ; mais ces deux modèles resteront dans la base de données : 🎜rrreee🎜Pour plus de commodité, attach
et detach< /code> permet également de transmettre un tableau d'identifiants : 🎜rrreee🎜🎜Association synchrone🎜🎜Vous pouvez également utiliser la méthode sync
pour créer Association plusieurs-à-plusieurs. La méthode sync
reçoit un tableau d'ID pour remplacer les enregistrements de la table intermédiaire. Parmi les enregistrements de la table intermédiaire, tous les enregistrements qui ne sont pas dans le tableau ID seront supprimés. Ainsi après l'opération, seuls les ID du tableau donné seront conservés dans la table intermédiaire : 🎜rrreee🎜 Vous pouvez également transmettre des données supplémentaires supplémentaires à la table intermédiaire par ID : 🎜rrreee🎜 Si vous ne souhaitez pas supprimer l'existant ID, vous pouvez utiliser la méthode syncWithoutDetaching
: 🎜rrreee🎜🎜Toggle association 🎜🎜L'association plusieurs-à-plusieurs fournit également toggle
Méthode utilisée pour "basculer" l'état attaché du tableau d'ID donné. Si l'ID donné a été ajouté dans la table intermédiaire, alors il sera supprimé, de même, si l'ID donné a été supprimé, il sera ajouté : 🎜rrreee🎜🎜🎜Enregistrer sur la table intermédiaire Données supplémentaires🎜🎜Lors du traitement relations plusieurs-à-plusieurs, la méthode de sauvegarde reçoit un tableau de données supplémentaire comme deuxième paramètre : 🎜rrreee🎜🎜Mettre à jour l'enregistrement de la table intermédiaire
Si vous devez mettre à jour un enregistrement existant dans la table intermédiaire, vous pouvez utiliser updateExistingPivot
. Cette méthode reçoit la clé étrangère de la table intermédiaire et du tableau de données à mettre à jour pour la mise à jour : updateExistingPivot
。此方法接收中间表的外键与要更新的数据数组进行更新:
rrreee更新父级时间戳
当一个模型属 belongsTo
或者 belongsToMany
另一个模型时, 例如 Comment
属于 Post
,有时更新子模型导致更新父模型时间戳非常有用。例如,当 Comment
模型被更新时,您要自动「触发」父级 Post
模型的 updated_at
时间戳的更新。Eloquent 让它变得简单。只要在子模型加一个包含关联名称的 touches
属性即可:
rrreee现在,当你更新一个 Comment
时,对应父级 Post
模型的 updated_at
字段同时也会被更新,使其更方便得知何时让一个 Post
rrreee
rrreee🎜Maintenant, lorsque vous mettez à jour un Comment
, le parent correspondant Post Le Le champ updated_at
du modèle code> sera également mis à jour, permettant de savoir plus facilement quand invalider le cache d'un modèle Post
: 🎜rrreee🎜Cet article est apparu pour la première fois sur 🎜 Site Web LearnKu.com🎜. 🎜🎜