如何使用数据库迁移和种子程序来抽象 Laravel 中的数据库设置

Migrationsseeders是由 Laravel PHP 框架提供的强大的数据库实用程序,允许开发人员快速启动、摧毁和重建应用程序的数据库。

在本指南中,我们将创建迁移和播种器,以填充Laravel演示应用程序的数据库,使用样本数据。

前提条件

为了遵循这个指南,你需要:

若您正在使用远程服务器,建议安装一个活跃的防火墙。 若要设置这些,请参阅我们的 Ubuntu 18.04 初始服务器设置指南

  • Docker 安装在您的服务器上,遵循 [Ubuntu 18.04 上如何安装和使用 Docker]的 步骤 1步骤 2
  • Docker Compose 安装在您的服务器上,遵循 [Ubuntu 18.04 上如何安装 Docker Compose]的 步骤 1

<$>[注意] 注意:在本指南中,我们将使用由Docker Compose管理的集装开发环境来运行该应用程序,但您也可以选择在LEMP服务器上运行该应用程序。

步骤 1 – 获取 demo 应用程序

要开始,我们将从其 GitHub 存储库中获取 Laravel 演示应用程序。我们对‘tutorial-02’分支感兴趣,其中包括一个 Docker Compose setup来在容器上运行该应用程序。

1cd ~
2curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-2.0.1.zip -o travellist.zip

由于我们将应用程序代码下载为.zip 文件,所以我们需要unzip命令来解包。

1sudo apt update

然后安装unzip包:

1sudo apt install unzip

接下来,卸载应用程序的内容:

1unzip travellist.zip

然后将未包装的目录更名为旅行者演示版,以便更容易访问:

1mv travellist-laravel-demo-tutorial-2.0.1 travellist-demo

在下一步,我们将创建一个 .env 配置文件来设置应用程序。

步骤 2 — 设置应用程序的 .env 文件

在 Laravel 中,一个 .env 文件用于设置 环境依赖配置,例如凭证和可能在部署之间有所不同的任何信息。

<$>[警告] 警告:环境配置文件包含有关您的服务器的敏感信息,包括数据库凭证和安全密钥。

.env 文件中包含的值将优先于位于 config 目录中的常规配置文件中设置的值。在新环境中的每个安装都需要一个定制的环境文件来定义数据库连接设置、调试选项和应用程序 URL 等内容,这些内容可能因应用程序所运行的环境而有所不同。

导航到‘travellist-demo’目录:

1cd travellist-demo

我们现在将创建一个新的 .env 文件来定制我们正在设置的开发环境的配置选项. Laravel 附带了一个例子.env 文件,我们可以复制以创建自己的:

1cp .env.example .env

使用nano或您所选择的文本编辑器打开此文件:

1nano .env

这就是你的.dll 文件现在的样子:

 1[label .env]
 2APP_NAME=Travellist
 3APP_ENV=dev
 4APP_KEY=
 5APP_DEBUG=true
 6APP_URL=http://localhost:8000 
 7
 8LOG_CHANNEL=stack
 9
10DB_CONNECTION=mysql
11DB_HOST=db
12DB_PORT=3306
13DB_DATABASE=travellist
14DB_USERNAME=travellist_user
15DB_PASSWORD=password
16

travellist演示应用程序的当前 .env’ 文件包含使用我们在本系列的最后一部分使用 Docker Compose 创建的集装箱化环境的设置。您不需要更改这些值,但您可以随意更改 DB_DATABASEDB_USERNAMEDB_PASSWORD,因为这些由我们的 docker-compose.yml` 文件自动引导来设置开发数据库。

如果您对文件进行任何更改,请确保将其保存并关闭,按CTRL + X,Y,然后按ENTER

<$>[注意] 注意:如果您选择在 LEMP服务器上运行应用程序,则需要更改突出值以反映您自己的数据库设置,包括DB_HOST变量。

步骤 3 – 使用 Composer 安装应用程序依赖

现在我们将使用 Composer,PHP的依赖管理工具,来安装应用程序的依赖,并确保我们能够执行手工命令。

用以下命令将您的 Docker Compose 环境带上。 这将为应用程序服务构建旅行者图像,并将nginxdb服务所需的额外的 Docker 图像拉进来,以创建应用程序环境:

1docker-compose up -d
 1[secondary_label Output]
 2Creating network "travellist-demo_travellist" with driver "bridge"
 3Building app
 4Step 1/11 : FROM php:7.4-fpm
 5 ---> fa37bd6db22a
 6Step 2/11 : ARG user
 7 ---> Running in 9259bb2ac034
 8 9Creating travellist-app   ... done
10Creating travellist-nginx ... done
11Creating travellist-db    ... done

此操作可能需要几分钟才能完成,一旦完成,我们就可以运行 Composer 来安装应用程序的依赖。

要在app服务容器中执行composer和其他命令,我们将使用docker-compose execexec命令允许我们在Docker Compose管理的容器上执行我们所选择的任何命令。

<$>[注意] 注意:如果您选择使用LEMP服务器运行演示应用程序,您应该忽略本指南中列出的命令的docker-compose exec app部分。

1composer install

美元

要在app容器中执行composer install,运行:

1docker-compose exec app composer install
1[secondary_label Output]
2Loading composer repositories with package information
3Installing dependencies (including require-dev) from lock file
4Package operations: 85 installs, 0 updates, 0 removals
5  - Installing doctrine/inflector (1.3.1): Downloading (100%)         
6  - Installing doctrine/lexer (1.2.0): Downloading (100%)         
7  - Installing dragonmantank/cron-expression (v2.3.0): Downloading (100%)     
8

当 Composer 完成安装应用程序的依赖性时,您将能够执行手工命令. 要测试应用程序是否能够连接到数据库,请运行以下命令,以清除任何现有表:

1docker-compose exec app php artisan db:wipe

此命令会将任何现有表放到配置的数据库中. 如果它成功运行,并且应用程序能够连接到数据库,则会看到这样的输出:

1[secondary_label Output]
2Dropped all tables successfully.

现在你已经安装了应用程序依赖性与Composer,你可以使用工匠工具来创建迁移和种子。

步骤 4 – 创建数据库迁移

使用Laravel的工匠命令行工具包含一系列可用于管理应用程序和启动新类的辅助命令。

1docker-compose exec app php artisan make:migration create_places_table

Laravel 继承了要执行的操作(‘创建’),表的名称(‘位置’),以及这个迁移是否会创建一个新表,基于为 make:migration 命令提供的描述名称。

你会看到类似于此的输出:

1[secondary_label Output]
2Created Migration: 2020_02_03_143622_create_places_table

这将在应用程序的数据库/迁移目录中生成一个新文件,自动生成的文件中包含的时刻印由Laravel用来确定应该执行哪个顺序的迁移。

使用您所选择的文本编辑器打开生成的迁移文件. 请记住用您自己的迁移文件名更换突出值:

1nano database/migrations/2020_02_03_143622_create_places_table.php

生成的迁移文件包含一个名为CreatePlacesTable的类:

 1[label database/migrations/2020_02_03_143622_create_places_table.php]
 2<?php
 3
 4use Illuminate\Database\Migrations\Migration;
 5use Illuminate\Database\Schema\Blueprint;
 6use Illuminate\Support\Facades\Schema;
 7
 8class CreatePlacesTable extends Migration
 9{
10    /**
11     * Run the migrations.
12     *
13     * @return void
14     */
15    public function up()
16    {
17        Schema::create('places', function (Blueprint $table) {
18            $table->bigIncrements('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('places');
31    }
32}

此类有两种方法:。这两种方法都包含可扩展的 bootstrap 代码,可定制迁移执行时会发生什么,以及在返回时会发生什么。

我们将修改方法,以便位置表反映我们在当前应用程序版本中已经使用的结构:

  • id:主要密钥字段.
  • 名称:地点的名称.
  • 访问过:这个地点是否已经被访问过。

Laravel Schema Builder 揭示了在数据库中创建、更新和删除表的方法. Blueprint 类定义了表的结构,并提供了 若干方法来抽象每个表字段的定义。

自动生成的代码会设置一个名为id的主要 id 字段. timestamps 方法会创建两个datetime字段,当数据被插入或更新到该表中时,底层数据库类别会自动更新它们。

我们的名称字段将是字符串,我们的访问字段将被设置为布尔式字段,我们还将为访问字段设置默认值为0,因此如果没有传递值,则意味着该地点尚未访问。

 1[label database/migrations/2020_02_03_143622_create_places_table.php]
 2 3    public function up()
 4    {
 5        Schema::create('places', function (Blueprint $table) {
 6            $table->bigIncrements('id');
 7            $table->string('name', 100);
 8            $table->boolean('visited')->default(0);
 9            $table->timestamps();
10        });
11    }
12

<$>[注] :您可以在 Laravel 文档中找到可用的列表。

在您自己的迁移脚本中包含两个突出的行后,保存并关闭文件。

您的迁移现在已经准备好通过手工迁移来执行,但这只会创建一个空的表;我们还需要能够输入样本数据用于开发和测试。

步骤5 - 创建数据库种子

一个 seeder 是用于在数据库中生成和插入样本数据(种子)的特殊类,这是开发环境中的一项重要功能,因为它允许您使用新数据库重新创建应用程序,使用您在数据库重新创建时必须手动插入的样本值。

现在我们将使用工匠命令来生成一个名为PlacesTableSeeder场所表的新种子类别:

1docker-compose exec app php artisan make:seeder PlacesTableSeeder

该命令将创建一个名为PlacesTableSeeder.php的新文件,在数据库/种子目录中。

1nano database/seeds/PlacesTableSeeder.php

这就是自动生成的 PlacesTableSeeder.php 文件的样子:

 1[label database/seeds/PlacesTableSeeder.php]
 2<?php
 3
 4use Illuminate\Database\Seeder;
 5
 6class PlacesTableSeeder extends Seeder
 7{
 8    /**
 9     * Run the database seeds.
10     *
11     * @return void
12     */
13    public function run()
14    {
15        //
16    }
17}

我们的新种子类包含一个名为运行的空格方法,当执行db:seed Artisan 命令时,该方法将被调用。

我们需要编辑运行方法,以便在数据库中添加示例数据的说明,我们将使用Laravel查询构建程序(https://laravel.com/docs/6.x/queries)来简化这个过程。

Laravel 查询构建程序为数据库操作提供流畅的界面,例如插入、更新、删除和检索数据。它还引入了对 SQL 注入攻击的保护措施。

要开始,我们将创建一个静态类变量,以保持我们想要插入数据库的所有样本位置作为一个数组,这将允许我们使用一个前方循环重复所有值,使用查询构建器将每个值插入数据库。

我们将这个变量称为$places:

 1[label database/seeds/PlacesTableSeeder.php]
 2<?php
 3
 4use Illuminate\Database\Seeder;
 5
 6class PlacesTableSeeder extends Seeder
 7{
 8    static $places = [
 9        'Berlin',
10        'Budapest',
11        'Cincinnati',
12        'Denver',
13        'Helsinki',
14        'Lisbon',
15        'Moscow',
16        'Nairobi',
17        'Oslo',
18        'Rio',
19        'Tokyo'
20    ];
21

接下来,我们需要在我们的PlacesTableSeeder类顶部包含一个使用声明,以便在整个代码中引用DB面貌:

1[label database/seeds/PlacesTableSeeder.php]
2<?php
3
4use Illuminate\Database\Seeder;
5use Illuminate\Support\Facades\DB;
6
7class PlacesTableSeeder extends Seeder
8

现在我们可以使用前方循环迭代$places数组值,并使用查询构建器将每个值插入我们的位置表中:

 1[label database/seeds/PlacesTableSeeder.php]
 2
 3    public function run()
 4    {
 5        foreach (self::$places as $place) {
 6            DB::table('places')->insert([
 7                'name' => $place,
 8                'visited' => rand(0,1) == 1
 9            ]);
10        }
11    }

前方循环通过$places静态数组的每个值进行迭代.在每个迭代中,我们使用DB面板在places表中插入一个新的行。

以下是所有更新后完整的PlacesTableSeeder类的样子:

 1[label database/seeds/PlacesTableSeeder.php]
 2<?php
 3
 4use Illuminate\Database\Seeder;
 5use Illuminate\Support\Facades\DB;
 6
 7class PlacesTableSeeder extends Seeder
 8{
 9    static $places = [
10        'Berlin',
11        'Budapest',
12        'Cincinnati',
13        'Denver',
14        'Helsinki',
15        'Lisbon',
16        'Moscow',
17        'Nairobi',
18        'Oslo',
19        'Rio',
20        'Tokyo'
21    ];
22
23    /**
24     * Run the database seeds.
25     *
26     * @return void
27     */
28    public function run()
29    {
30        foreach (self::$places as $place) {
31            DB::table('places')->insert([
32                'name' => $place,
33                'visited' => rand(0,1) == 1
34            ]);
35        }
36    }
37}

保存并关闭文件,当您完成这些更改。

我们需要编辑主要的DatabaseSeeder类以包括我们刚刚创建的播种器的呼叫。

使用nano或您最喜欢的编辑器打开database/seeds/DatabaseSeeder.php文件:

1nano database/seeds/DatabaseSeeder.php

DatabaseSeeder类看起来像任何其他种子:它从Seeder类扩展,并具有运行方法. 我们将更新此方法,以包括调用PlacesTableSeeder

在您的DatabaseSeeder类内更新当前的运行方法,通过删除被评论的行,并用以下突出代码取代它:

1[label database/seeds/DatabaseSeeder.php]
2
3    public function run()
4    {
5        $this->call(PlacesTableSeeder::class);
6    }
7...

以下是更新后完整的「DatabaseSeeder」类型:

 1[label database/seeds/DatabaseSeeder.php]
 2<?php
 3
 4use Illuminate\Database\Seeder;
 5
 6class DatabaseSeeder extends Seeder
 7{
 8    /**
 9     * Seed the application's database.
10     *
11     * @return void
12     */
13    public function run()
14    {
15        $this->call(PlacesTableSeeder::class);
16    }
17}

保存并关闭文件,当您完成更新其内容。

我们现在已经完成了为我们的场所表设置迁移和播种器,在下一步,我们将看到如何执行它们。

步骤 6 – 运行数据库迁移和种子

我们会设置应用程序加密密钥,然后从浏览器访问应用程序来测试Web服务器。

要生成 Laravel 所需的加密密钥,您可以使用手工密钥:生成命令:

1docker-compose exec app php artisan key:generate

一旦密钥被生成,您将能够通过将浏览器指向您的服务器主机名或IP地址在端口8000上访问应用程序:

1http://server_host_or_ip:8000

你会看到这样的页面:

MySQL error

这意味着应用程序可以连接到数据库,但无法找到名为位置的表. 我们现在将使用以下迁移手工命令创建位置表:

1docker-compose exec app php artisan migrate

你会得到类似于此的输出:

 1[secondary_label Output]
 2Migration table created successfully.
 3Migrating: 2014_10_12_000000_create_users_table
 4Migrated:  2014_10_12_000000_create_users_table (0.06 seconds)
 5Migrating: 2014_10_12_100000_create_password_resets_table
 6Migrated:  2014_10_12_100000_create_password_resets_table (0.06 seconds)
 7Migrating: 2019_08_19_000000_create_failed_jobs_table
 8Migrated:  2019_08_19_000000_create_failed_jobs_table (0.03 seconds)
 9Migrating: 2020_02_10_144134_create_places_table
10Migrated:  2020_02_10_144134_create_places_table (0.03 seconds)

您会注意到,我们已经设置了create_places_table迁移,并执行了其他几次迁移,这些迁移是在Laravel安装时自动生成的,尽管我们现在不会使用这些额外的表,但在我们扩展应用程序时,他们将需要注册用户和计划的工作。

我们需要运行db:seed命令以将数据库种植到我们的样本位置:

1docker-compose exec app php artisan db:seed

这将运行我们的播种器,并将我们在我们的PlacesTableSeeder类内定义的样本值插入。

1[secondary_label Output]
2Seeding: PlacesTableSeeder
3Seeded:  PlacesTableSeeder (0.06 seconds)
4Database seeding completed successfully.

现在,在您的浏览器中重新加载应用程序页面,您将看到一个类似于此的页面:

Demo Laravel Application

每当您需要从头开始时,您可以将所有数据库表放下:

1docker-compose exec app php artisan db:wipe
1[secondary_label Output]
2Dropped all tables successfully.

若要运行应用迁移并将表种在一个命令中,您可以使用:

1docker-compose exec app php artisan migrate --seed
 1[secondary_label Output]
 2Migration table created successfully.
 3Migrating: 2014_10_12_000000_create_users_table
 4Migrated:  2014_10_12_000000_create_users_table (0.06 seconds)
 5Migrating: 2014_10_12_100000_create_password_resets_table
 6Migrated:  2014_10_12_100000_create_password_resets_table (0.07 seconds)
 7Migrating: 2019_08_19_000000_create_failed_jobs_table
 8Migrated:  2019_08_19_000000_create_failed_jobs_table (0.03 seconds)
 9Migrating: 2020_02_10_144134_create_places_table
10Migrated:  2020_02_10_144134_create_places_table (0.03 seconds)
11Seeding: PlacesTableSeeder
12Seeded:  PlacesTableSeeder (0.06 seconds)
13Database seeding completed successfully.

如果您想返回迁移,您可以运行:

1docker-compose exec app php artisan migrate:rollback

通常,它会删除通过迁移类创建的所有表,只留下可能手动创建的任何其他表。

1[secondary_label Output]
2Rolling back: 2020_02_10_144134_create_places_table
3Rolled back:  2020_02_10_144134_create_places_table (0.02 seconds)
4Rolling back: 2019_08_19_000000_create_failed_jobs_table
5Rolled back:  2019_08_19_000000_create_failed_jobs_table (0.02 seconds)
6Rolling back: 2014_10_12_100000_create_password_resets_table
7Rolled back:  2014_10_12_100000_create_password_resets_table (0.02 seconds)
8Rolling back: 2014_10_12_000000_create_users_table
9Rolled back:  2014_10_12_000000_create_users_table (0.02 seconds)

当您对应用模型进行更改时,滚动命令特别有用,并且无法使用db:wipe命令 - 例如,如果多个系统依赖于相同的数据库。

结论

在本指南中,我们已经看到了如何使用数据库迁移和播种器来促进Laravel 6应用程序的开发和测试数据库的设置。

作为下一步,您可能需要查看 Laravel 文档,以获取有关如何使用 查询构建程序以及如何使用 清晰模型的更多细节,以进一步抽象应用程序的数据库架构。

Published At
Categories with 技术
comments powered by Disqus