迁移和种子文件允许您构建、修改和填充数据库表。它们主要由一个插件更新文件使用,并与插件的版本历史记录配对。所有类都存储在插件的updates目录中。迁移应该讲述您的数据库历史故事,并且这个故事可以向前和向后播放,以构建和拆除表。
您可以使用命令行脚手架工具生成一个迁移文件。第一个参数指定作者和插件名称。第二个参数指定迁移名称。
php artisan create:migration Acme.Blog CreatePostsTable迁移文件应定义一个扩展 October\Rain\Database\Updates\Migration 类的类,并包含两个方法:up 和 down。up 方法用于向数据库添加新表、列或索引,而 down 方法应简单地撤销 up 方法执行的操作。在这两个方法中,您可以使用模式构建器来清晰地创建和修改表。例如,让我们看一个创建 october_blog_posts 表的示例迁移:
use October\Rain\Database\Schema\Blueprint;
use October\Rain\Database\Updates\Migration;
return new class extends Migration
{
public function up()
{
Schema::create('october_blog_posts', function($table)
{
$table->increments('id');
$table->string('title');
$table->string('slug')->index();
$table->text('excerpt')->nullable();
$table->text('content');
$table->timestamp('published_at')->nullable();
$table->boolean('is_published')->default(false);
$table->timestamps();
});
}
public function down()
{
Schema::drop('october_blog_posts');
}
}创建表时,您可以使用模式构建器的任何列方法来定义表的列 (详见下文).
要创建新的数据库表,请使用 Schema facade 上的 create 方法。create 方法接受两个参数。第一个是表的名称,而第二个是一个 Closure,它接收一个用于定义新表的 对象。
Schema::create('users', function ($table) {
$table->increments('id');
});你可以使用 hasTable 和 hasColumn 方法检查表或列是否存在。
if (Schema::hasTable('users')) {
//
}
if (Schema::hasColumn('users', 'email')) {
//
}如果您想对非默认数据库连接执行架构操作,请使用 connection 方法。
Schema::connection('foo')->create('users', function ($table) {
$table->increments('id');
});要为表设置存储引擎,请在 schema builder 上设置 engine 属性。
Schema::create('users', function ($table) {
$table->engine = 'InnoDB';
$table->increments('id');
});要重命名现有的数据库表,请使用 rename 方法。
Schema::rename($from, $to);要删除现有表,您可以使用 drop 或 dropIfExists 方法。
Schema::drop('users');
Schema::dropIfExists('users');要更新现有表,我们将使用 Schema 门面上的 table 方法。 类似于 create 方法, table 方法接受两个参数,表的名称和一个接收用于向表中添加列的对象的 Closure:
Schema::table('users', function ($table) {
$table->string('email');
});当然,模式构建器包含多种列类型,可供你在构建表时使用。
| Command | Description |
|---|---|
$table->bigIncrements('id'); | Incrementing ID (primary key) using a "UNSIGNED BIG INTEGER" equivalent. |
$table->bigInteger('votes'); | BIGINT equivalent for the database. |
$table->binary('data'); | BLOB equivalent for the database. |
$table->boolean('confirmed'); | BOOLEAN equivalent for the database. |
$table->char('name', 4); | CHAR equivalent with a length. |
$table->date('created_at'); | DATE equivalent for the database. |
$table->dateTime('created_at'); | DATETIME equivalent for the database. |
$table->decimal('amount', 5, 2); | DECIMAL equivalent with a precision and scale. |
$table->double('column', 15, 8); | DOUBLE equivalent with precision, 15 digits in total and 8 after the decimal point. |
$table->enum('choices', ['foo', 'bar']); | ENUM equivalent for the database. |
$table->float('amount'); | FLOAT equivalent for the database. |
$table->increments('id'); | Incrementing ID (primary key) using a "UNSIGNED INTEGER" equivalent. |
$table->integer('votes'); | INTEGER equivalent for the database. |
$table->json('options'); | JSON equivalent for the database. |
$table->jsonb('options'); | JSONB equivalent for the database. |
$table->longText('description'); | LONGTEXT equivalent for the database. |
$table->mediumInteger('numbers'); | MEDIUMINT equivalent for the database. |
$table->mediumText('description'); | MEDIUMTEXT equivalent for the database. |
$table->morphs('taggable'); | Adds INTEGER taggable_id and STRING taggable_type. |
$table->nullableTimestamps(); | Same as timestamps(), except allows NULLs. |
$table->rememberToken(); | Adds remember_token as VARCHAR(100) NULL. |
$table->smallInteger('votes'); | SMALLINT equivalent for the database. |
$table->softDeletes(); | Adds deleted_at column for soft deletes. |
$table->string('email'); | VARCHAR equivalent column. |
$table->string('name', 100); | VARCHAR equivalent with a length. |
$table->text('description'); | TEXT equivalent for the database. |
$table->time('sunrise'); | TIME equivalent for the database. |
$table->tinyInteger('numbers'); | TINYINT equivalent for the database. |
$table->timestamp('added_on'); | TIMESTAMP equivalent for the database. |
$table->timestamps(); | Adds created_at and updated_at columns. |
除了上面列出的列类型之外,还有其他几种列“修饰符”可以在添加列时使用。例如,要使列“可空”,您可以使用 nullable 方法。
Schema::table('users', function ($table) {
$table->string('email')->nullable();
});以下是所有可用的列修饰符。此列表不包含索引修饰符。
| Modifier | Description |
|---|---|
->nullable() | Allow NULL values to be inserted into the column |
->default($value) | Specify a "default" value for the column |
->unsigned() | Set integer columns to UNSIGNED |
->first() | Place the column "first" in the table (MySQL Only) |
->after('column') | Place the column "after" another column (MySQL Only) |
->comment('my comment') | Add a comment to a column (MySQL Only) |
change 方法允许您将现有列修改为新类型,或修改列的属性。例如,您可能希望增加字符串列的大小。要查看 change 方法的实际应用,我们来将 name 列的大小从 25 增加到 50。
Schema::table('users', function ($table) {
$table->string('name', 50)->change();
});我们还可以修改一个列,使其可为空:
Schema::table('users', function ($table) {
$table->string('name', 50)->nullable()->change();
});要重命名列,您可以使用 renameColumn 方法在 Schema 构建器上。
Schema::table('users', function ($table) {
$table->renameColumn('from', 'to');
});重命名包含 enum 列的表中的列目前不支持。
要删除一个列,使用 Schema 构建器上的 dropColumn 方法。
Schema::table('users', function ($table) {
$table->dropColumn('votes');
});您可以从表中删除多列,通过向 dropColumn 方法传递一个列名数组。
Schema::table('users', function ($table) {
$table->dropColumn(['votes', 'avatar', 'location']);
});模式构建器支持几种索引类型。首先,让我们看一个指定列的值应唯一的例子。要创建索引,我们可以简单地将 unique 方法链式调用到列定义上。
$table->string('email')->unique();或者,你可以在定义列之后创建索引。例如:
$table->unique('email');你甚至可以向索引方法传递一个列数组来创建复合索引。
$table->index(['account_id', 'created_at']);在大多数情况下,你应该手动指定索引的名称作为第二个参数,以避免系统自动生成一个过长的名称。
$table->index(['account_id', 'created_at'], 'account_created');| Command | Description |
|---|---|
$table->primary('id'); | Add a primary key. |
$table->primary(['first', 'last']); | Add composite keys. |
$table->unique('email'); | Add a unique index. |
$table->index('state'); | Add a basic index. |
要重命名索引,请使用由模式构建器蓝图提供的 renameIndex 方法。此方法接受当前索引名称作为其第一个参数,并接受所需名称作为其第二个参数。
$table->renameIndex('from', 'to')要删除索引,您必须指定索引的名称。如果未手动指定名称,系统将自动生成一个,只需连接表名,被索引列的名称,和索引类型。以下是一些示例:
| Command | Description |
|---|---|
$table->dropPrimary('users_id_primary'); | Drop a primary key from the "users" table. |
$table->dropUnique('users_email_unique'); | Drop a unique index from the "users" table. |
$table->dropIndex('geo_state_index'); | Drop a basic index from the "geo" table. |
还支持创建外键约束,外键约束用于在数据库级别强制参照完整性。例如,我们来定义 posts 表上的 user_id 列,该列引用 users 表上的 id 列:
Schema::table('posts', function ($table) {
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
});与之前一样,你可以通过向 foreign 方法传递第二个参数来手动为该约束指定一个名称:
$table->foreign('user_id', 'user_foreign')
->references('id')
->on('users');您还可以指定针对约束的"删除时"和"更新时"属性的所需操作:
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade');要删除外键,您可以使用 dropForeign 方法。外键约束使用与索引相同的命名约定。因此,如果未手动指定,我们将连接表名和约束中的列,然后以 "_foreign" 作为名称的后缀:
$table->dropForeign('posts_user_id_foreign');与迁移文件类似,Seeder 类默认只包含一个名为 run 的方法并且应该继承 Seeder 类。run 方法在更新过程执行时被调用。在此方法中,你可以按照你希望的方式将数据插入到数据库中。你可以使用 查询构建器 手动插入数据或者使用你的 模型类。在下面的示例中,我们将使用 User 模型在 run 方法内部创建一个新用户。
<?php namespace Acme\Users\Updates;
use Seeder;
use Acme\Users\Models\User;
class SeedUsersTable extends Seeder
{
public function run()
{
$user = User::create([
'email' => 'user@example.tld',
'login' => 'user',
'password' => 'password123',
'password_confirmation' => 'password123',
'first_name' => 'Actual',
'last_name' => 'Person',
'is_activated' => true
]);
}
}另外,也可以使用 Db::table 查询构建器 方法。
public function run()
{
$user = Db::table('users')->insert([
'email' => 'user@example.tld',
'login' => 'user',
// ...
]);
}在 DatabaseSeeder 类中,你可以使用 call 方法来执行额外的填充类。使用 call 方法可以让你将数据库填充拆分为多个文件,以便任何一个填充类都不会变得过于庞大。只需传递你希望运行的填充类的名称即可。
public function run()
{
$this->call(\Acme\Users\Updates\UserTableSeeder::class);
$this->call(\Acme\Users\Updates\PostsTableSeeder::class);
$this->call(\Acme\Users\Updates\CommentsTableSeeder::class);
}