新增一对一多态关联,并更新多态关联
修改理由:
相关信息:
- 类型:文档文章
- 文章: 模型关联
- 文档: 《Laravel 5.7 中文文档(5.7)》
此投稿已在 6年前 合并。
内容修改:
| Old | New | Differences |
|---|---|---|
| 7 | 7 | - [一对多 (反向)](#one-to-many-inverse) |
| 8 | 8 | - [多对多](#many-to-many) |
| 9 | 9 | - [远程一对多](#has-many-through) |
| 10 | - [多态关联](#polymorphic-relations) | |
| 11 | - [多对多多态关联](#many-to-many-polymorphic-relations) | |
| 10 | - [多态关联](#polymorphic-relations) | |
| 11 | - [一对一](#one-to-one-polymorphic-relations) | |
| 12 | - [一对多](#one-to-many-polymorphic-relations) | |
| 13 | - [多对多](#many-to-many-polymorphic-relations) | |
| 14 | - [自定义多态类型](#custom-polymorphic-types) | |
| 12 | 15 | - [查询关联](#querying-relations) |
| 13 | 16 | - [关联方法 Vs. 动态属性](#relationship-methods-vs-dynamic-properties) |
| 14 | 17 | - [基于存在的关联查询](#querying-relationship-existence) | … | … |
| 33 | 36 | - [一对多](#one-to-many) |
| 34 | 37 | - [多对多](#many-to-many) |
| 35 | 38 | - [远程一对多](#has-many-through) |
| 36 | - [多态关联](#polymorphic-relations) | |
| 37 | - [多对多多态关联](#many-to-many-polymorphic-relations) | |
| 39 | - [一对一 (多态关联)](#one-to-one-polymorphic-relations) | |
| 40 | - [一对多 (多态关联)](#one-to-many-polymorphic-relations) | |
| 41 | - [多对多 (多态关联)](#many-to-many-polymorphic-relations) | |
| 38 | 42 | |
| 39 | 43 | <a name="defining-relationships"></a> |
| 40 | 44 | ## 定义关联 | … | … |
| 423 | 427 | } |
| 424 | 428 | |
| 425 | 429 | <a name="polymorphic-relations"></a> |
| 426 | ### 多态关联 | |
| 430 | ## 多态关联 | |
| 431 | ||
| 432 | 多态关联允许一个模型在单个关联上属于多个其他模型。 | |
| 433 | ||
| 434 | <a name="one-to-one-polymorphic-relations"></a> | |
| 435 | ### 一对一 (多态关联) | |
| 427 | 436 | |
| 428 | 437 | #### 数据表结构 |
| 429 | 438 | |
| 430 | 多态关联允许一个模型在单个关联上属于多个其他模型。例如,想象一下使用你应用的用户可以「评论」文章和视频。使用多态关联,你可以用一个 `comments` 表同时满足这两个使用场景。让我们来看看构建这种关联所需的数据表结构: | |
| 439 | 一对一的多态关联类似于简单的一对一关联,但目标模型可以在单个关联上属于多个其他模型。例如,博客文章和用户可以共享与图像模型的多态关联,使用一对一的多态关联,您可以用一个 `images` 表同时满足这两个使用场景。让我们来看看构建这种关联所需的数据表结构: | |
| 440 | ||
| 441 | posts | |
| 442 | id - integer | |
| 443 | title - string | |
| 444 | body - text | |
| 445 | ||
| 446 | users | |
| 447 | id - integer | |
| 448 | title - string | |
| 449 | url - string | |
| 450 | ||
| 451 | images | |
| 452 | id - integer | |
| 453 | body - text | |
| 454 | imageable_id - integer | |
| 455 | imageable_type - string | |
| 456 | ||
| 457 | `images` 表中有两个需要注意的重要字段 `imageable_id` 和 `imageable_type`。`imageable_id` 用来保存文章或者用户的 ID 值,而 `imageable_type` 用来保存所属模型的类名。Eloquent 使用 `imageable_type` 来决定我们访问关联模型时,要返回的父模型的「类型」。 | |
| 458 | ||
| 459 | #### 模型结构 | |
| 460 | ||
| 461 | 接下来,我们来看看创建这种关联所需的模型定义: | |
| 462 | ||
| 463 | <?php | |
| 464 | ||
| 465 | namespace App; | |
| 466 | ||
| 467 | use Illuminate\Database\Eloquent\Model; | |
| 468 | ||
| 469 | class Image extends Model | |
| 470 | { | |
| 471 | /** | |
| 472 | * 获得拥有此图像的模型。 | |
| 473 | */ | |
| 474 | public function imageable() | |
| 475 | { | |
| 476 | return $this->morphTo(); | |
| 477 | } | |
| 478 | } | |
| 479 | ||
| 480 | class Post extends Model | |
| 481 | { | |
| 482 | /** | |
| 483 | * 获得此文章的图像。 | |
| 484 | */ | |
| 485 | public function image() | |
| 486 | { | |
| 487 | return $this->morphOne('App\Image', 'imageable'); | |
| 488 | } | |
| 489 | } | |
| 490 | ||
| 491 | class User extends Model | |
| 492 | { | |
| 493 | /** | |
| 494 | * 获得此用户的图像。 | |
| 495 | */ | |
| 496 | public function image() | |
| 497 | { | |
| 498 | return $this->morphOne('App\Image', 'imageable'); | |
| 499 | } | |
| 500 | } | |
| 501 | ||
| 502 | #### 获取多态关联 | |
| 503 | ||
| 504 | 一旦你的数据库表准备好、模型定义完成后,就可以通过模型来访问关联了。例如,我们只要简单地使用 `image` 动态属性,就可以获得某篇文章的图像: | |
| 505 | ||
| 506 | $post = App\Post::find(1); | |
| 507 | ||
| 508 | $image = $post->image; | |
| 509 | ||
| 510 | 你也可以在多态模型上,通过访问调用了 `morphTo` 的关联方法获得多态关联的拥有者。在当前例子中,是 `Image` 模型的 `imageable` 方法。所以,我们可以使用动态属性来访问这个方法: | |
| 511 | ||
| 512 | $image = App\Image::find(1); | |
| 513 | ||
| 514 | $imageable = $image->imageable; | |
| 515 | ||
| 516 | `Image` 模型的 `imageable` 关联会返回 `Post` 或者 `User` 实例,这取决于图像所属的模型类型。 | |
| 517 | ||
| 518 | <a name="one-to-many-polymorphic-relations"></a> | |
| 519 | ### 一对多 (多态关联) | |
| 520 | ||
| 521 | #### 数据表结构 | |
| 522 | ||
| 523 | 一对多的多态关联类似于简单的一对多关联,但目标模型可以在单个关联上属于多个其他模型。例如,您的应用程序的用户可以「评论」文章和视频,使用一对多的多态关联,您可以用一个 `comments` 表同时满足这两个使用场景。让我们来看看构建这种关联所需的数据表结构: | |
| 431 | 524 | |
| 432 | 525 | posts |
| 433 | 526 | id - integer | … | … |
| 445 | 538 | commentable_id - integer |
| 446 | 539 | commentable_type - string |
| 447 | 540 | |
| 448 | `comments` 表中有两个需要注意的重要字段 `commentable_id` 和 `commentable_type`。`commentable_id` 用来保存文章或者视频的 ID 值,而 `commentable_type` 用来保存所属模型的类名。 | |
| 541 | `comments` 表中有两个需要注意的重要字段 `commentable_id` 和 `commentable_type`。`commentable_id` 用来保存文章或者视频的 ID 值,而 `commentable_type` 用来保存所属模型的类名。Eloquent 使用 `commentable_type` 来决定我们访问关联模型时,要返回的父模型的「类型」。 | |
| 449 | 542 | |
| 450 | 543 | #### 模型结构 |
| 451 | 544 | … | … |
| 508 | 601 | |
| 509 | 602 | `Comment` 模型的 `commentable` 关联会返回 `Post` 或者 `Video` 实例,这取决于评论所属的模型类型。 |
| 510 | 603 | |
| 511 | ||
| 512 | ||
| 513 | ||
| 514 | ||
| 515 | ||
| 516 | ||
| 517 | ||
| 518 | ||
| 519 | ||
| 520 | ||
| 521 | ||
| 522 | ||
| 523 | ||
| 524 | 604 | |
| 525 | 605 | <a name="many-to-many-polymorphic-relations"></a> |
| 526 | ### 多对多 | |
| 527 |
| |
| 528 | #### | |
| 529 |
| |
| 530 | ||
| 606 | ### 多对多 (多态关联) | |
| 607 | ||
| 608 | #### 数据表结构 | |
| 609 | ||
| 610 | 「多对多」的多态关联比「一对一」和「一对多」的多态关联稍微复杂一些。举例而言,一个 `Post` 和 `Video` 模型共享一个 `Tag` 模型。使用多对多的多态关联将允许你去有一个在 `Video` 和 `Post` 之间共同使用一个唯一的标签列表。首先,让我们来看一下数据表结构: | |
| 531 | 611 | |
| 532 | 612 | ``` |
| 533 | 613 | posts | … | … |
| 550 | 630 | |
| 551 | 631 | #### 模型结构 |
| 552 | 632 | |
| 553 | 接下来,我们要 | |
| 633 | 接下来,我们要在模型上定义关联关系。 `Post` 和 `Video` 模型会有一个共同的 `tags` 方法,它们会被基础的模型的 `morphToMany` 方法调用: | |
| 554 | 634 | |
| 555 | 635 | ```php |
| 556 | 636 | <?php | … | … |
| 623 | 703 | // |
| 624 | 704 | } |
| 625 | 705 | ``` |
| 706 | ||
| 707 | ||
| 708 | <a name="custom-polymorphic-types"></a> | |
| 709 | ### 自定义多态类型 | |
| 710 | ||
| 711 | 默认,Laravel 会使用完全限定类名作为关联模型保存在多态模型上的类型字段值。比如,在上面的例子中,`Comment` 属于 `Post` 或者 `Video`,那么 `commentable_type`的默认值对应地就是 `App\Post` 和 `App\Video`。但是,你可能希望将数据库与程序内部结构解耦。那样的话,你可以定义一个「多态映射表」来指示 Eloquent 使用每个模型自定义类型字段名而不是类名: | |
| 712 | ||
| 713 | use Illuminate\Database\Eloquent\Relations\Relation; | |
| 714 | ||
| 715 | Relation::morphMap([ | |
| 716 | 'posts' => 'App\Post', | |
| 717 | 'videos' => 'App\Video', | |
| 718 | ]); | |
| 719 | ||
| 720 | 你可以在 `AppServiceProvider` 中的 `boot` 函数中使用 `Relation::morphMap` 方法注册「多态映射表」,或者使用一个独立的服务提供者注册。 | |
| 721 | ||
| 722 | ||
| 626 | 723 | <a name="querying-relations"></a> |
| 627 | 724 | ## 查询关联 |
| 628 | 725 | … | … |
| 672 | 769 | } |
| 673 | 770 | ``` |
| 674 | 771 | |
| 675 | 动态属性就像 | |
| 772 | 动态属性就像「懒加载」,也就是说当你确实会使用到它们的使用,它会自动进行加载。由于这一特性,开发者经常会使用到 [懒加载](#eager-loading) 去实现那些在获取到模型后必须要加载的关联模型。懒加载对 那些在模型上定了关联关系 SQL 查询上有了性能的提升,它们对 SQL 查询语句的执行次数有了明显的减少(也就是 n + 1性能问题)。 | |
| 676 | 773 | |
| 677 | 774 | <a name="querying-relationship-existence"></a> |
| 678 | 775 | ### 查询关联关系是否存在 | … | … |
| 690 | 787 | $posts = App\Post::has('comments', '>=', 3)->get(); |
| 691 | 788 | ``` |
| 692 | 789 | |
| 693 | `has` 方法也可可以接受以 | |
| 790 | `has` 方法也可可以接受以 「.」 点形式的嵌套加载。举例来说,你要获取到至少包含一条评论和投票的博客: | |
| 694 | 791 | |
| 695 | 792 | ```php |
| 696 | 793 | // 获取至少有一条评论的文章,并加载评论的投票信息 | … | … |
| 698 | 795 | ``` |
| 699 | 796 | |
| 700 | 797 | 如果你想要做更多特性,你还可以使用 `whereHas` 和 ` |
| 701 | orWhereHas` 方法,在方法中,你可以指定 | |
| 798 | orWhereHas` 方法,在方法中,你可以指定 「where」 条件在你的 `has` 语句之中。这些方法允许你在关联查询之中添加自定义的条件约束,比如检查评论的内容: | |
| 702 | 799 | |
| 703 | 800 | ```php |
| 704 | 801 | // 获取所有至少有一条评论的文章且评论内容以 foo 开头 | … | … |
| 723 | 820 | })->get(); |
| 724 | 821 | ``` |
| 725 | 822 | |
| 726 | 你可能要使用 | |
| 823 | 你可能要使用 「.」 点符号去执行一个嵌套的加载。举例来说,如下语句,将会获取到所有文章,同时加载了那些没有被禁用的用户的文章评论: | |
| 727 | 824 | |
| 728 | 825 | ```php |
| 729 | 826 | $posts = App\Post::whereDoesntHave('comments.author', function ($query) { | … | … |
| 771 | 868 | <a name="eager-loading"></a> |
| 772 | 869 | ## 懒加载 |
| 773 | 870 | |
| 774 | 当通过动态属性的方法去加载关联数据时,它已经是在 | |
| 871 | 当通过动态属性的方法去加载关联数据时,它已经是在 「懒加载」 了。也就是说,当你在未使用到该关联数据时,它其实是并没有查询数据的。然而, 当你在查询父级模型时, Eloquent 允许渴求式加载关联数据,渴求式加载避免了 N + 1 查询问题。为了说明 N + 1 的查询问题,思考 `Book` 模型关联了 `Auhtor` : | |
| 775 | 872 | |
| 776 | 873 | ```php |
| 777 | 874 | <?php | … | … |
| 832 | 929 | |
| 833 | 930 | #### 嵌套式的渴求式加载 |
| 834 | 931 | |
| 835 | 实现渴求式加载也很简单,你可以使用 | |
| 932 | 实现渴求式加载也很简单,你可以使用 「.」 点语法去实现。譬如,我们需要加载所有的书籍,并且包含作者以及作者的联系方式。那么我们就可以这样写: | |
| 836 | 933 | |
| 837 | 934 | ```php |
| 838 | 935 | $books = App\Book::with('author.contacts')->get(); |
关于 LearnKu