美文网首页
Laravel数据库迁移与数据填充

Laravel数据库迁移与数据填充

作者: 噫那里有条咸鱼 | 来源:发表于2017-12-27 15:31 被阅读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表会直接删除它。

    • ps: laravel会自动记录执行过的迁移,每个迁移只会执行一次。

    接下来我们修改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());
            });
    }
    
    • factory接受两个参数:一个是Eloquent模型,另一个是批量插入的数据量。

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

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

    php artisan db:seed
    

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

    php artisan db:seed --class=UsersTableSeeder
    
    • PS:因为faker随机生成的名字长度会超过20,导致插入数据库时报错,解决方法:创建一个针对users表的迁移,将name的长度改为100就好了。
    Schema::table('users', function (Blueprint $table) {
        if (Schema::hasColumn('users','name')) {
            $table->string('name', 20)->comment('用户名')->change();
        } 
    });
    

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

    users表 user_card表

    2017-12-27

    相关文章

      网友评论

          本文标题:Laravel数据库迁移与数据填充

          本文链接:https://www.haomeiwen.com/subject/xenygxtx.html