如何在 Laravel Eloquent 中创建一对多关系

示范 Landing Laravel应用程序,你设置为本系列的先决条件,包含一个单一的数据库表存储链接. 在本教程中,你将修改这个初始的数据库结构,包括第二个表,你将使用它来组织链接到 列表

对于我们将在本系列中使用的链接和列表示例来说,每个链接都只是一个列表的一部分,但每个列表都可以有多个链接。这种关系也被称为一个(https://en.wikipedia.org/wiki/One-to-many_(data_model))的关系。

一对多关系发生时,一个项目,我们将称之为类型 A,可以链接到多个类型 B 的项目,但相反并不真实:类型 B 的项目只能链接到类型 _A 的 项目。

创建一个LinkList模型

要开始,你需要创建一个模型和一个数据库表来代表一个链接的 列表。然后,你会更新现有的 ** 链接 模型和表,以包括两种模型之间的关系。由于术语列表仅限于PHP内部,你将无法用这个术语命名你的新模型。

首先,请确保您在应用程序目录中:

1cd ~/landing-laravel

使用手工艺人创建一个新模型:

1docker-compose exec app php artisan make:model LinkList

这将在应用程序/模型目录中生成一个新的模型类:

1app/Model/LinkList.php

如果你看看你的app/Console/Commands目录,你会注意到已经有一个名为LinkList.php的类文件. 这不应该与你刚刚创建的Eloquent模型混淆。

为了避免未来的混淆,现在是改名该类及其命令签名以另一个名称的好时机。在这种情况下,使用类名称LinkShow,因为这个名称也描述了该类所做的事情。

1mv app/Console/Commands/LinkList.php app/Console/Commands/LinkShow.php

然后,在代码编辑器中打开app/Console/Commands/LinkShow.php文件,将类名称从LinkList更改为LinkShow,并将命令签名从link:list更改为link:show,如下代码列表中的突出行。

 1[label app/Console/Commands/LinkShow.php]
 2<?php
 3
 4namespace App\Console\Commands;
 5
 6use App\Models\Link;
 7use Illuminate\Console\Command;
 8
 9class LinkShow extends Command
10{
11    /**
12     * The name and signature of the console command.
13     *
14     * @var string
15     */
16    protected $signature = 'link:show';
17
18    /**
19     * The console command description.
20     *
21     * @var string
22     */
23    protected $description = 'List links saved in the database';
24
25    /**
26     * Create a new command instance.
27     *
28     * @return void
29     */
30    public function __construct()
31    {
32        parent::__construct();
33    }
34
35    /**
36     * Execute the console command.
37     *
38     * @return int
39     */
40    public function handle()
41    {
42        $headers = [ 'id', 'url', 'description' ];
43        $links = Link::all(['id', 'url', 'description'])->toArray();
44        $this->table($headers, $links);
45
46        return 0;
47    }
48}

完成后保存并关闭文件. 若要确保一切按预期工作,请运行新改名为link:show的手工命令:

1docker-compose exec app php artisan link:show

你会收到这样的输出:

1[secondary_label Output]
2+----+-------------------------------------------------+----------------------------------+
3| id | url                                             | description                      |
4+----+-------------------------------------------------+----------------------------------+
5| 1  | https://digitalocean.com/community              | DigitalOcean Community           |
6| 2  | https://digitalocean.com/community/tags/laravel | Laravel Tutorias at DigitalOcean |
7| 3  | https://digitalocean.com/community/tags/php     | PHP Tutorials at DigitalOcean    |
8+----+-------------------------------------------------+----------------------------------+

创建LinkList模型的迁移

你用以前的手工制作:模型命令生成的新的app/Model/LinkList.php类包含一个新的Eloquent类的通用代码. 与其他ORM(如Doctrine)不同,Eloquent不会改变数据库结构,只处理数据本身。

使用 Eloquent 处理数据的这种方法意味着您不需要为LinkList类设置任何属性,因为它们将从该模型的数据库表结构中推断出来。

结构数据库操作通常在Laravel中通过 数据库迁移进行处理。迁移允许开发人员编程定义数据库的结构变化,例如创建、修改和删除表。

现在,您将创建一个新的迁移以设置数据库中的 ** 列表** 表。

Laravel 默认中包含的工匠命令行工具包含几种辅助方法来启动新的组件,如控制器、模型、迁移等。

1docker-compose exec app php artisan make:migration create_link_lists_table
1[secondary_label Output]
2 Created Migration: 2021_07_07_152554_create_link_lists_table

此命令将生成一个新的文件在您的 Laravel 应用程序中的数据库/迁移目录下,使用基于当前日期和时间和迁移名称的自动生成的名称。

使用代码编辑器,打开生成的迁移文件。

 1[label database/migrations/2021_07_07_152554_create_link_lists_table.php]
 2<?php
 3
 4use Illuminate\Database\Migrations\Migration;
 5use Illuminate\Database\Schema\Blueprint;
 6use Illuminate\Support\Facades\Schema;
 7
 8class CreateLinkListsTable extends Migration
 9{
10    /**
11     * Run the migrations.
12     *
13     * @return void
14     */
15    public function up()
16    {
17        Schema::create('link_lists', function (Blueprint $table) {
18            $table->id();
19            $table->timestamps();
20        });
21    }
22
23    /**
24     * Reverse the migrations.
25     *
26     * @return void
27     */
28    public function down()
29    {
30        Schema::dropIfExists('link_lists');
31    }
32}

在使用Artisan 迁移 ' 指令时,迁移采用up() ' 方法。 您的表格定义就在这里, 默认它会创建一个 id 主键字段和两个乘法字段( 创建- at更新- at ) , 定义为时间戳( ) 。 斯克马法. 在创建和更新模型时,这些字段会自动由口号填充。 " 下 " 法在使用 " Artisan回滚 " 命令回滚时称为 " 下 " 法,通常执行代码来放下表格或回转结构变化.

您将更改方法以包括以下字段:

*‘标题’:代表本列表的标题的字符串 *‘描述’:代表列表的描述的字符串 *‘slug’:基于标题的独特、短的字符串,通常用于创建易于使用的URL。

在一对多关系中, many 页面(在本场景中与 links 表相符)是将列参考(或外部密钥)保留在其他元素(与 ** lists** 表相符)的页面,这意味着您将不得不稍后修改 ** links** 表,以包含将该表链接到 ** lists** 表的参考字段。

另一方面, ** 列表** 表不需要任何特殊字段来引用其链接。

将迁移文件中的当前内容替换为以下代码:

 1[label database/migrations/2021_07_07_152554_create_link_lists_table.php]
 2<?php
 3
 4use Illuminate\Database\Migrations\Migration;
 5use Illuminate\Database\Schema\Blueprint;
 6use Illuminate\Support\Facades\Schema;
 7
 8class CreateLinkListsTable extends Migration
 9{
10    /**
11     * Run the migrations.
12     *
13     * @return void
14     */
15    public function up()
16    {
17        Schema::create('link_lists', function (Blueprint $table) {
18            $table->id();
19            $table->timestamps();
20            $table->string('title', 60);
21            $table->string('slug', 60)->unique();
22            $table->text('description')->nullable();
23        });
24    }
25
26    /**
27     * Reverse the migrations.
28     *
29     * @return void
30     */
31    public function down()
32    {
33        Schema::dropIfExists('link_lists');
34    }
35}

完成后保存文件。

更新链接迁移

接下来,在代码编辑器中打开现有的 links 迁移文件. 在演示项目中,您将在以下途径中找到迁移:

12020_11_18_165241_create_links_table.php

首先,包括一个使用指令,指向LinkList类的完全合格类名称,在文件的开始和最后一个使用行之后:

1
2use Illuminate\Support\Facades\Schema;
3use App\Models\LinkList;
4...

接下来,在表定义中,在方法中,并在设置描述字段的行之后,包括下面的行:

1$table->text('description');
2$table->foreignIdFor(LinkList::class);

foreignIdFor() 方法创建了一个对所参照的 Eloquent 模型的外钥列,它使用默认命名来设置与所参照的表的主要密钥字段相关的字段。

完成迁移时,整个迁移类应该是这样的:

 1[label database/migrations/2020_11_18_165241_create_links_table.php]
 2<?php
 3
 4use Illuminate\Database\Migrations\Migration;
 5use Illuminate\Database\Schema\Blueprint;
 6use Illuminate\Support\Facades\Schema;
 7use App\Models\LinkList;
 8
 9class CreateLinksTable extends Migration
10{
11    /**
12     * Run the migrations.
13     *
14     * @return void
15     */
16    public function up()
17    {
18        Schema::create('links', function (Blueprint $table) {
19            $table->id();
20            $table->string('url', 200);
21            $table->text('description');
22            $table->foreignIdFor(LinkList::class);
23            $table->timestamps();
24        });
25    }
26
27    /**
28     * Reverse the migrations.
29     *
30     * @return void
31     */
32    public function down()
33    {
34        Schema::dropIfExists('links');
35    }
36}

然后,删除数据库,然后再次运行迁移命令,以使用更新的迁移文件重建数据库结构:

1docker-compose exec app php artisan db:wipe
2docker-compose exec app php artisan migrate

配置精彩的模型关系

数据库表现在已设置,但您仍然需要配置 Eloquent 模型来定义它们之间的关系。

列表模型上,它是关系的 侧,您将设置一个名为链接的新方法,该方法将作为代理来访问与每个列表相关的链接,使用母类Illuminate\Database\Eloquent\Model中的hasMany方法。

在您的代码编辑器中,打开文件 app/Model/LinkList.php. 用以下内容替换当前的通用代码:

 1[label app/Model/LinkList.php]
 2<?php
 3
 4namespace App\Models;
 5
 6use Illuminate\Database\Eloquent\Factories\HasFactory;
 7use Illuminate\Database\Eloquent\Model;
 8
 9class LinkList extends Model
10{
11    use HasFactory;
12
13    public function links()
14    {
15        return $this->hasMany(Link::class);
16    }
17}

完成后保存文件。

接下来,您将编辑该关系的 ** 多个** 侧,以便重新引用列表模型,以便链接可以访问其相应的列表。

在您的代码编辑器中打开链接模型:

1app/Model/Link.php

用以下代码取代您的Link.php文件中的当前内容:

 1[label app/Model/Link.php]
 2<?php
 3
 4namespace App\Models;
 5
 6use Illuminate\Database\Eloquent\Model;
 7
 8class Link extends Model
 9{
10    public function link_list()
11    {
12        return $this->belongsTo(LinkList::class);
13    }
14}

完成后保存文件。

随着这两个模型的更新,您的数据库现在已完全配置,但目前是空的。

Published At
Categories with 技术
comments powered by Disqus