Laravel数据库迁移与数据填充

2017-12-27  本文已影响356人  噫那里有条咸鱼

如果在开发过程中,你曾经有过手动在数据库结构中添加字段的经历,导致不同的开发者的数据库不同步,那么数据库迁移可以帮你解决这个问题。
数据库迁移就像是数据库的版本控制,可以让团队轻松修改并共享应用程序的数据库结构。迁移通常会搭配上 Laravel 的数据库结构构造器来更方便地构建数据库结构。


数据库迁移

项目的创建,环境配置等请参考laravel官方文档,此处不再赘述。

创建迁移

进入到项目根目录,执行以下命令:

php artisan make:migration create_users_table --create=users

--table 选项可用来指定数据表的名称
--create 选项指定该迁移被执行时会创建的新数据表
--path 选项会为迁移指定一个自定义路径

新的迁移文件将会被放置在 database/migrations 目录下。每个迁移文件的名称都包含了一个时间戳以 时间戳_XXX的形式命名。

迁移文件 create_users_table

打开刚才生成的迁移文件可以看到文件内容如下:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}

可以看到laravel已经帮我们自动创建了updown方法:
up 方法可为数据库添加新的数据表、字段或索引。
down 方法则是用于执行回滚操作。
Schema::create接受两个参数。第一个是要创建表的表名;第二个是一个闭包(匿名函数),获取用于定义新表的 Blueprint 对象。
这里的Schema::dropIfExists('users');会判断如果存在users表会直接删除它。

接下来我们修改up方法,laravel的链式写法很轻松就能知道要做的操作

  public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');//主键自增ID
            $table->string('name',20)->comment('用户名');//string默认是数据库的Verchar类型,长度20,comment备注
            $table->string('email',255)->unique()->comment('邮箱');//unique添加唯一索引
            $table->string('password')->comment("密码");
            $table->rememberToken();
            $table->timestamps();//添加created_at和updated_at字段
        });
    }

执行迁移

接下来执行php artisan migrate命令来运行所有未运行过的迁移

执行迁移
生成的数据表默认字符集为utf8mb4,排序规则utf8mb4_unicode_ci
Users数据表

回滚操作

觉得表创建有问题是可以有后悔药吃的,运行以下命令即可

php artisan migrate:rollback
回滚操作

php artisan migrate:rollback命令是对上一次执行的「批量」迁移回滚,其中可能包括多个迁移文件,在 rollback 命令后加上 step 参数,可以限制回滚迁移的个数。

比如想回滚最后的 3个迁移:

php artisan migrate:rollback --step=3

回滚应用程序中的所有迁移:

php artisan migrate:reset

检查数据表或字段是否存在

重新创建users表后,突然想添加软删除功能,这时候可以创建针对users表的迁移:

php artisan make:migration change_users_table --table=users
创建迁移

编辑up方法:

public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            if (!Schema::hasColumn('users','deleted_at')) {
                $table->softDeletes();//添加软删除功能,会在users表中添加deleted_at字段
            }
        });
    }

hasColumn方法用来检查字段是否存,第一个参数是要检查的表,第二个参数是要检查的字段。
要检查users表是否存在可以使用hasTable方法。

执行php artisan migrate命令,从下图的执行结果可以看deleted_at字段已经添加进users表了

users表

数据填充

我们可以使用laravel框架的seeder类来执行数据填充,所有由框架生成的 seeders 都将被放置在 database/seeds 目录下。

php artisan make:seeder UsersTableSeeder

让我们修改UserTableSeeder下的run方法:

<?php

use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;

class DatabaseSeeder extends Seeder
{
    /**
     * 运行数据库填充
     *
     * @return void
     */
    public function run()
    {
        DB::table('users')->insert([
            'name' => str_random(10),
            'email' => str_random(10).'@gmail.com',
            'password' => bcrypt('secret'),
        ]);
    }
}

然后修改DatabaseSeeder下的run方法,在 DatabaseSeeder 类中,可以使用 call 方法执行额外的填充类,使用 call 方法允许你将数据库填充分解成多个文件。

<?php

use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;

class DatabaseSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $this->call(UserTableSeeder::class);
    }
}

执行php artisan db:seed后,数据库中就生成了一条新的用户数据。

模型工厂

有了users表,我们还可以创建一张user_card表,一位用户可以拥有多张会员卡。这时候要每张表单独填充数据就比较麻烦了,这时候就可以使用 模型工厂 来轻松地生成大量数据库记录。

首先做好准备工作,为我们的user_card创建迁移:

php artisan make:migration create_user_card_table --create=user_card

修改up方法并执行迁移:

public function up()
    {
        Schema::create('user_card', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id');
            $table->string('number',20)->comment('卡号');
            $table->timestamps();
            $table->softDeletes();
        });
    }

为User模型添加一对多的关系:

public function userCards()
{
    return $this->hasMany('App\UserCard');
}

接下来打开 database/factories/UserFactory.php 文件,该文件包含了一个工厂定义:

<?php

use Faker\Generator as Faker;

/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| This directory should contain each of the model factory definitions for
| your application. Factories provide a convenient way to generate new
| model instances for testing / seeding your application's database.
|
*/

$factory->define(App\User::class, function (Faker $faker) {
    static $password;

    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'password' => $password ?: $password = bcrypt('secret'),
        'remember_token' => str_random(10),
    ];
});

Faker实例提供了很多可用的随机数据,比如我们要填充人名,使用$faker->name即可,它最后会生成如Prof. Shanna Jacobs这样的高度拟真数据,不需要自己再去瞎编什么test001之类的数据。unique保证了邮箱的唯一,safeEmail是防止生成真正的邮箱,用了呢个保留的那啥。。。忘了。。。

想要深入了解Faker的可以参考:https://github.com/fzaninotto/Faker

再为user_card定义一个工厂,在database/factories路径下创建UserCardFactory.php文件,因为user_card中的用户ID是关联的users表的,所以这里只需要为卡号生成一个随机数就可以了。

<?php

use Faker\Generator as Faker;

$factory->define(App\UserCard::class, function (Faker $faker) {
    return [
        'number' => random_int(10000,9999999),
    ];
});

然后我们修改UserTableSeeder下的run方法:

public function run()
{
    //模型工厂
    factory(App\User::class, 50)
        ->create()
        ->each(function ($u) {
            $u->userCards()->save(factory(App\UserCard::class)->make());
        });
}

上面run方法中的语句表示创建 50 个用户,为每个用户创建关联,并将其存到数据库中。

最后我们只需要执行命令生成数据:

php artisan db:seed

也可以指定执行一个特定的 seeder 类:

php artisan db:seed --class=UsersTableSeeder
Schema::table('users', function (Blueprint $table) {
    if (Schema::hasColumn('users','name')) {
        $table->string('name', 20)->comment('用户名')->change();
    } 
});

现在我们可以查看数据库,会发现新增了50条关联数据。

users表 user_card表

2017-12-27

上一篇下一篇

猜你喜欢

热点阅读