Bennent_G 3年前

修改理由:

链接失效,无法访问

相关信息:


此投稿已在 3年前 合并。

内容修改:

红色背景 为原始内容

绿色背景 为新增或者修改的内容

OldNewDifferences
1  
21# Eloquent: 关联
32
43- [简介](#introduction)
 
5150- [多态一对多](#one-to-many-polymorphic-relations)
5251- [多态多对多](#many-to-many-polymorphic-relations)
5352
54 
55 
 53
 54
5655<a name="defining-relationships"></a>
5756## 定义关联
5857
 
9291
9392   return $this->hasOne(Phone::class, 'foreign_key');
9493
95 
96 
 94
 95
9796另外,Eloquent 假设外键的值是与父模型的主键(Primary Key)相同的。换句话说,Eloquent 将会通过 `Phone` 记录的 `user_id` 列中查找与用户表的 `id` 列相匹配的值。如果你希望使用自定义的主键值,而不是使用 `id` 或者模型中的 `$primaryKey` 属性,你可以给 `hasOne` 方法传递第三个参数:
9897
9998   return $this->hasOne(Phone::class, 'foreign_key', 'local_key');
 
132131       return $this->belongsTo(User::class, 'foreign_key');
133132   }
134133
135 
136 
 134
 135
137136如果父模型不使用 `id` 字段来作为主键,或者您想要使用其他的字段来匹配相关联的模型,那么您可以向 `belongsTo` 方法传递第三个参数,这个参数是在父模型中自己定义的字段:
138137
139138   /**
 
178177       //
179178   }
180179
181 
182 
 180
 181
183182由于所有的关系都可以看成是查询构造器,所以您也可以通过链式调用的方式,在 `comments` 方法中继续添加条件约束:
184183
185184   $comment = Post::find(1)->comments()
 
226225
227226Eloquent 通过检查关联方法的名称,从而在关联方法名称后面加上 `_` ,然后再加上父模型 (Post)的主键名称,以此来作为默认的外键名。因此,在上面这个例子中,Eloquent 将会默认 `Post` 模型在 `comments` 表中的外键是 `post_id`。
228227
229 
230 
 228
 229
231230但是,如果您的外键不遵循这种约定的话,那么您可以传递一个自定义的外键名来作为 `belongsTo` 方法的第二个参数:
232231
233232   /**
 
283282       });
284283   }
285284
286 
287 
 285
 286
288287<a name="has-one-through"></a>
289288### 远程一对一
290289
 
350349       }
351350   }
352351
353 
354 
 352
 353
355354<a name="has-many-through"></a>
356355### 远程一对多
357356
 
414413       }
415414   }
416415
417 
418 
 416
 417
419418<a name="many-to-many"></a>
420419## 多对多关联
421420多对多关联比 `hasOne` 和 `hasMany` 关联稍微复杂些。举个例子,一个用户可以拥有多个角色,同时这些角色也可以分配给其他用户。例如,一个用户可是「作者」和「编辑」;当然,这些角色也可以分配给其他用户。所以,一个用户可以拥有多个角色,一个角色可以分配给多个用户。
 
460459   }
461460}
462461```
463 
464 
 462
 463
465464一旦关联关系被定义后,你可以通过 `roles`「动态属性」获取用户角色:
466465
467466   use App\Models\User;
 
506505       }
507506   }
508507
509 
510 
 508
 509
511510如你所见,除了引入模型 `App\Models\User` 外,其它与在 `User` 模型中定义的完全一样。由于我们重用了 `belongsToMany` 方法,自定义连接表表名和自定义连接表里的键的字段名称在这里同样适用。
512511
513512<a name="retrieving-intermediate-table-columns"></a>
 
535534
536535> 注意:使用 Eloquent 自动维护时间戳的中间表需要同时具有 `created_at` 和 `updated_at` 时间戳字段。
537536
538 
539 
 537
 538
540539<a name="customizing-the-pivot-attribute-name"></a>
541540#### 自定义 `pivot` 属性名称
542541
 
572571
573572如果你想定义一个自定义模型来表示多对多关系的中间表,你可以在定义关系时调用 `using` 方法。
574573
575 
576 
 574
 575
577576自定义多对多中间表模型都必须扩展自 `Illuminate\Database\Eloquent\Relations\Pivot` 类,自定义多对多(多态)中间表模型必须继承 `Illuminate\Database\Eloquent\Relations\MorphPivot` 类。例如,我们在写 `Role` 模型的关联时,使用自定义中间表模型 `RoleUser`:
578577
579578   <?php
 
626625多态关联允许目标模型借助单个关联从属于多个模型。例如,你正在构建一个允许用户共享博客文章和视频的应用程序,其中 `Comment` 模型可能同时从属于 `Post` 和 `Video` 模型。
627626
628627<a name="one-to-one-polymorphic-relations"></a>
629 
630 
 628
 629
631630### 一对一 (多态)
632631
633632<a name="one-to-one-polymorphic-table-structure"></a>
 
695694       }
696695   }
697696
698 
699 
 697
 698
700699<a name="one-to-one-polymorphic-retrieving-the-relationship"></a>
701700#### 获取关联
702701
 
755754       commentable_id - integer
756755       commentable_type - string
757756
758 
759 
 757
 758
760759<a name="one-to-many-polymorphic-model-structure"></a>
761760#### 模型结构
762761
 
849848       taggable_id - integer
850849       taggable_type - string
851850
852 > 技巧:在深入研究多态多对多关系之前,你可能会从阅读有关典型 [多对多关系](#many-to-many) 的文档中受益。
853 
 851> 技巧:在深入研究多态多对多关系之前,你可能会从阅读有关典型 [多对多关系](#many-to-many) 的文档中受益。
 852
854853<a name="many-to-many-polymorphic-model-structure"></a>
855854#### 模型结构
856855
 
903902       }
904903   }
905904
906 
907 
 905
 906
908907<a name="many-to-many-polymorphic-retrieving-the-relationship"></a>
909908#### 获取关联
910909
 
945944   ]);
946945
947946可以在 `App\Providers\AppServiceProvider` 的 `boot` 函数中注册 `morphMap`,或者创建一个单独的服务提供者。
948 
949 
 947
 948
950949您可以在运行时使用 `getMorphClass` 方法确定给定模型的别名。相反,您可以使用 `Relation::getMorphedModel` 方法来确定与别名相关联的类名:
951950
952951   use Illuminate\Database\Eloquent\Relations\Relation;
 
978977
979978因为所有的 Eloquent 关联都是通过方法定义的,你可以调用这些方法来获取关联的实例,而无需真实执行查询来获取相关的模型。此外,所有的 Eloquent 关联也可以用作[查询生成器](/docs/laravel/8.x/queries),允许你在最终对数据库执行 SQL 查询之前,继续通过链式调用添加约束条件。
980979
981 
982 
 980
 981
983982例如,假设有一个博客系统,它的 `User` 模型有许多关联的 `Post` 模型:
984983
985984   <?php
 
10381037           })
10391038           ->get();
10401039
1041 
1042 
 1040
 1041
10431042上面的示例将生成以下 SQL。 请注意,逻辑分组已对约束进行了正确分组,并且查询仍然限定于特定用户:
10441043
10451044```sql
 
10781077   // 查出至少有三条评论的文章...
10791078   $posts = Post::has('comments', '>=', 3)->get();
10801079
1081 
1082 
 1080
 1081
10831082也可以用「点」语法构造嵌套的 `has` 语句。例如,查出至少有一条评论和图片的文章:
10841083
10851084   // 查出至少有一条带图片的评论的文章...
 
11181117       $query->where('content', 'like', 'code%');
11191118   })->get();
11201119
1121 
1122 
 1120
 1121
11231122您可以使用“点”符号对嵌套关系执行查询。 例如,以下查询将检索所有没有评论的帖子; 但是,有未被禁止的作者评论的帖子将包含在结果中:
11241123
11251124   use Illuminate\Database\Eloquent\Builder;
 
11701169       }
11711170   )->get();
11721171
1173 
1174 
 1172
 1173
11751174<a name="querying-all-morph-to-related-models"></a>
11761175#### 查询所有关联模型
11771176
 
12241223   echo $posts[0]->comments_count;
12251224   echo $posts[0]->pending_comments_count;
12261225
1227 
1228 
 1226
 1227
12291228<a name="deferred-count-loading"></a>
12301229#### 延迟加载计数
12311230
 
12741273### 计算多态关联关系的数量
12751274
12761275如果你想预加载多态关联关系以及这个关联关系关联的其他关联关系的计数统计,可以通过将`with` 方法与 `morphTo`关系和`morphWithCount` 方法结合来实现。
1277 
1278 
 1276
 1277
12791278在这个例子中,我们假设 `Photo` 和 `Post` 模型可以创建 `ActivityFeed` 模型。 我们将假设 `ActivityFeed` 模型定义了一个名为 `parentable` 的多态关联关系,它允许我们为给定的 `ActivityFeed` 实例检索父级 `Photo` 或 `Post` 模型。 此外,让我们假设`Photo` 模型有很多`Tag` 模型、`Post` 模型有很多`Comment` 模型。
12801279
12811280假如我们想要检索 `ActivityFeed` 实例并为每个 `ActivityFeed` 实例预先加载 `parentable` 父模型。 此外,我们想要检索与每张父照片关联的标签数量以及与每个父帖子关联的评论数量:
 
13241323       }
13251324   }
13261325
1327 
1328 
 1326
 1327
13291328我们检索所有书籍及其作者:
13301329
13311330   use App\Models\Book;
 
13711370<a name="nested-eager-loading-morphto-relationships"></a>
13721371#### 嵌套预加载 `morphTo` 关联
13731372
1374 
1375 
 1373
 1374
13761375如果你希望加载一个 `morphTo` 关系,以及该关系可能返回的各种实体的嵌套关系,可以将 `with` 方法与 `morphTo` 关系的 `morphWith` 方法结合使用。 为了帮助说明这种方法,让我们参考以下模型:
13771376
13781377   <?php
 
14431442       }
14441443   }
14451444
1446 
1447 
 1445
 1446
14481447如果你想从单个查询的 `$with` 属性中删除一个预加载,你可以使用 `without` 方法:
14491448
14501449   $books = Book::without('author')->get();
 
14871486       ]);
14881487   }])->get();
14891488
1490 
1491 
 1489
 1490
14921491在这个例子中,Eloquent 只会预先加载未被隐藏的帖子,并且视频的 `type` 值为 `educational`。
14931492
14941493<a name="lazy-eager-loading"></a>
 
15381537
15391538在这个例子中,让我们假设 `Event` 、`Photo` 和 `Post` 模型可以创建 `ActivityFeed` 模型。此外,让我们假设 `Event` 模型属于 `Calendar` 模型,`Photo` 模型与 `Tag` 模型相关联,`Post` 模型属于 `Author` 模型。
15401539
1541 
1542 
 1540
 1541
15431542使用这些模型定义和关联关系,我们方可以检索 `ActivityFeed` 模型实例,并立即加载所有 `parentable` 模型及其各自的嵌套关系:
15441543
15451544   $activities = ActivityFeed::with('parentable')
 
15871586   // 所有评论,包括新保存的评论...
15881587   $post->comments;
15891588
1590 
1591 
 1589
 1590
15921591<a name="the-push-method"></a>
15931592#### 递归保存模型和关联数据
15941593
 
16231622       ['message' => 'Another new comment.'],
16241623   ]);
16251624
1626 你还可以使用 `findOrNew`、`firstOrNew`、`firstOrCreate` 和 `updateOrCreate` 方法来 [创建和更新关系模型](https://laravel.com/docs/laravel/8.x/eloquent#other-creation-methods)。
 1625你还可以使用 `findOrNew`、`firstOrNew`、`firstOrCreate` 和 `updateOrCreate` 方法来 [创建和更新关系模型](https://laravel.com/docs/8.x/eloquent#Upserts)。
16271626
16281627> 技巧:在使用 `create` 方法前,请务必确保查看过本文档的 [批量赋值](/docs/laravel/8.x/eloquent#mass-assignment) 章节。
16291628
 
16401639
16411640   $user->save();
16421641
1643 
1644 
 1642
 1643
16451644当移除 `belongsTo` 关联时,可以使用 `dissociate` 方法。此方法会将关联外键设置为 `null` :
16461645
16471646   $user->account()->dissociate();
 
16921691
16931692   $user->roles()->sync([1, 2, 3]);
16941693
1695 
1696 
 1694
 1695
16971696你也可以通过 ID 传递额外的附加数据到中间表:
16981697
16991698   $user->roles()->sync([1 => ['expires' => true], 2, 3]);
 
17521751   }
17531752
17541753> 注意:只有使用 Eloquent 的 `save` 方法更新子模型时,才会更新父模型时间戳。
 1754  
17551755
1756