本文首发于 https://jaychen.ccphp
做者 JayChenlaravel
Laravel 中提供了数据库迁移的方式来管理数据库,想象一个场景:在一个多人开发的项目中,你的同事修改了某个数据库结构并修改了代码,经过 git 你能够即时的同步同事修改的代码,可是数据库结构,你只能经过手工的方式来复制同事修改的 SQL 语句,执行以保证数据库的结构一致。那么,Laravel 中的数据库迁移概念,就是用于解决团队中保证数据库结构一致的方案。github
migration 使用很是简单,编写必定的 php 代码并执行,那么 Laravel 就会自动的更新数据库。假设你的同事要修改数据库某个字段,那么只要编写 php 代码,接着你经过 git 更新了代码,执行 migrate 操做以后,你的数据库结构就和他的同步了。下面咱们就来看具体的使用方法。sql
Laravel 把编写数据库改动的 php 代码称为迁移,能够经过 php artisan make:migration filename
的方式来建立迁移文件。假设你须要建立一张新的 user 表,那么你能够经过执行 php artisan make:migration create_user_table --create=user
来建立一个迁移文件,执行命令会在 database/migrations/
目录下创建一个 文件建立时间_filename
的 php 文件,那么这个文件就是咱们接下来用来编写数据库结构变化的文件了。这里要提一点,虽说建立迁移文件的名称能够随意,可是为了管理方便,最好文件名能够体现要执行的数据库操做,好比这里咱们要建立一张 user 表,因此文件名称为 create_user_table
。数据库
php artisan make:migration filename
有两个可选参数闭包
--create=tablename
代表该迁移是用来建立表。--table=tablename
代表该迁移是用来对 tablename 这张表进行操做。咱们建立出来的迁移文件 create_user_table
会包含两个方法。函数
public function up() {
Schema::create('user', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
}
public function down() {
Schema::dropIfExists('user');
}
复制代码
这两个方法是互逆的操做,好比咱们能够再 up
方法中编写咱们要建立的 user 表的相关信息,而 down
方法中则是删除 user 表的操做。这样,咱们就能够作到回滚操做,当咱们建立 user 表以后发现某个字段名写错了,就能够经过 down
来删除 user 表,进而从新创建 user 表。测试
假设 user 表有 id,username,email
三个字段,那么能够再 up 方法中写this
public function up() {
Schema::create('user', function (Blueprint $table) {
$table->increments('id')->index()->comment('用户id');
$table->string('name')->default('')->comment('用户名');
$table->string('email')->nullable()->comment('用户邮箱');
$table->timestamps();
});
}
复制代码
通常,咱们的逻辑会在闭包函数中写。上面的代码,即时不能彻底明白,也能够大概猜出如下几点:
increments
方法,因此 id 为 auto_increment
,调用了 index
方法说明给 id 添加了索引,最后 comment
等同于注释。string
方法说明 name 是 varchar/char
类型的,default
定义了 name 字段的默认值。nullable
方法说明运行 email 字段为空。Laravel 中的方法是知足你对 sql 语句的全部操做,若是你须要定义一个类型为 text 的字段,那么能够调用 text()
方法,更多的方法说明能够参见文档 Laravel 数据库结构构造器。
咱们已经编写好了 user 表的结构,接下来执行 php artisan migrate
,Laravel 会根据 create
方法自动为咱们建立 user 表。至此,咱们已经成功的经过 Larvel 的迁移功能来实现建立表。
使用 Laravel 的迁移功能能够有后悔药吃。
执行 php artisan migrate
建立 user 表以后,以为不行,不要 user 这张表,因而你打算删除这张表。那么这时候咱们就要使用刚刚说到的 down
方法了。
public function down() {
Schema::dropIfExists('user');
}
复制代码
这里 Laarvel 已经为咱们写好逻辑了,dropIfExists
函数就是用来删除表,咱们只须要执行 php artisan migrate :rollback
就能够回滚到执行 php artisan migrate
以前的状态。
除了建立表,也能够用迁移记录表的其余任何操做,包括修改表属性,修改字段等等操做。这里再举个例子说明如何用迁移来对表进行重命名。
php artisan make:migration rename_user_to_users --table user
来建立迁移文件。up
方法中写咱们要重命名表的逻辑。public function up() {
Schema::table('user', function (Blueprint $table) {
Schema::rename('user','users');
});
}
复制代码
down
方法中编写撤销重命名操做的逻辑。public function up() {
Schema::table('user', function (Blueprint $table) {
//
Schema::rename('users','user');
});
}
复制代码
php artisan migrate
就就能够完成对 user 表的重命名操做。若是须要回滚,只要执行 php artisan migrate:rollback
。你会发现,若是执行一次迁移以后,若是执行第二次迁移是不会重复执行的,这是由于 Laravel 会在数据库中创建一张 migrations
的表来记录哪些已经进行过迁移。
基本的 migration 介绍就到这里,以上的内容能够应对大部分的需求,若是须要更详细的介绍,可能须要阅读 Laravel 那不知所云的文档了。:)
Laravel 中除了 migration 以外,还有一个 seeder 的东西,这个东西用于作数据填充。假设项目开发中须要有一些测试数据,那么一样能够经过编写 php 代码来填充测试数据,那么经过 git 同步代码,全部的人均可以拥有一份一样的测试数据。
一样,数据填充在 Laravel 中被称为 Seeder,若是须要对某张表填充数据,须要先创建一个 seeder。经过执行 php artisan make:seeder UserTableSeeder
来生成一个 seeder 类。这里咱们但愿填充数据的表示 test 表,因此名字为 UserTableSeeder
。固然这个名字不是强制性的,只是为了作到见名知意。
建立 UserTableSeeder 以后会在 database/seeders
目录下生成一个 UserTableSeeder
类,这个类只有一个 run 方法。你能够在 run
方法中写插入数据库的代码。假设咱们使用 DB facade 来向 test 表插入数据。
class UserTableSeeder extends Seeder {
public function run() {
DB::table('users')->insert($insertData);
}
}
复制代码
编写完代码以后,执行 php artsian db:seeder --class= UserTableSeeder
来进行数据填充。执行完毕以后查看数据库已经有数据了。
若是咱们有多个表要进行数据填充,那么不可能在编写完 php 代码以后,逐个的执行 php artisan db:seeder --class=xxxx
来进行填充。有一个简便的方法。在 DatabaseSeeder
的 run
方法中添加一行 $this->call(UserTableSeeder::class);
,而后执行 php artisan db:seeder
,那么 Laravel 就会执行 DatabaseSeeder
中的 run
方法,而后逐个执行迁移。
和 migration 不一样,若是屡次执行 php artisan db:seeder
就会进行屡次数据填充。
加入你想一次性插入大量的测试数据 ,那么在 run
方法中使用 DB facade 来逐个插入显然不是一个好的方法。Laravel 中提供了一种模型工厂的方式来建立建立大量的数据。
模型工厂,意味着本质实际上是一个工厂模式。那么,在使用模型工厂建立数据须要作两件事情
Laravel 中经过执行 php artisan make:factory UserFactory --model=User
来为 User Model 建立一个工厂类,该文件会放在 database/factory
目录下。打开该文件能够看到以下代码:
$factory->define(App\User::class, function (Faker $faker) {
return [
//
];
});
复制代码
这里, return 的值就是咱们第 2 步调用工厂获取到的数据。生成数据的逻辑也只须要写在闭包函数中就能够。这里须要提一下 Faker 这个类。这是一个第三方库,Laravel 集成了这个第三方库。这个库的做用很好玩:**用于生成假数据。**假设 User 表须要插入 100 个用户,那么就须要 100 个 username,那么你就没必要本身写逻辑生成大量的 test01,test02 这样子幼稚的假数据,直接使用 Faker 类,会替你生成大量逼真的 username。(我也不知道这个算不算无聊了 :)。。。)。
如今假设 User 表有 id, email, username 三个字段,那么我要生成 100 个用户,首先在工厂类中实现逻辑。
$factory->define(App\Models\User::class, function (Faker $faker) {
return [
// 直接调用 faker API 生成假数据,更多 faker 相关查看 文档。
'username' => $faker->name,
'email' => $faker->unique()->safeEmail,
];
});
复制代码
如今,咱们已经定义好了工厂,如今咱们就要在 UserSeeder@run
函数中使用模型工厂来生成测试数据。
class UserTableSeeder extends Seeder {
public function run() {
factory(App\User::class)->times(10)->make()->each(function($user,$index){
$user->save();
});
}
}
复制代码
run
函数中这一波行云流水的链式调用在我刚刚开始接触 Laravel 的时候也是一脸黑线,不过习惯以后感受这代码可读性确实很强
factory(App\User::class)
指明返回哪一个工厂,参数 App\User::class
就是工厂的惟一标识。这里咱们在定义工厂的时候 define
的第一个参数已经指明了。->times(10)
指明须要工厂模式生成 10 个 User 数据。即会调用 10 次 define
函数的第二个参数。->make()
把生成的 10 个 User 数据封装成 Laravel 中的集合对象。->each()
是 Laravel 集合中的函数,each
函数会针对集合中的每一个元素进行操做。这里直接把数据保存到数据库。好了,数据迁移和数据填充的基本操做也就这些了。更多复杂的用法。。。。也不必定能用上。