Laravel数据库迁移与数据填充
如果在开发过程中,你曾经有过手动在数据库结构中添加字段的经历,导致不同的开发者的数据库不同步,那么数据库迁移可以帮你解决这个问题。
数据库迁移就像是数据库的版本控制,可以让团队轻松修改并共享应用程序的数据库结构。迁移通常会搭配上 Laravel 的数据库结构构造器来更方便地构建数据库结构。
数据库迁移
项目的创建,环境配置等请参考laravel官方文档,此处不再赘述。
创建迁移
进入到项目根目录,执行以下命令:
php artisan make:migration create_users_table --create=users
--table 选项可用来指定数据表的名称
--create 选项指定该迁移被执行时会创建的新数据表
--path 选项会为迁移指定一个自定义路径
新的迁移文件将会被放置在 database/migrations
目录下。每个迁移文件的名称都包含了一个时间戳以 时间戳_XXX的形式命名。
打开刚才生成的迁移文件可以看到文件内容如下:
<?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已经帮我们自动创建了
up
和down
方法:
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表了
数据填充
我们可以使用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