# 数据库迁移

## 无符号整型

作为迁移的外键，请使用 `unsignedInteger()` 类型或 `integer()->unsigned()` 来替代 `integer()` ，否则将得到 SQL 错误。

```php
Schema::create('employees', function (Blueprint $table) {
    $table->unsignedInteger('company_id');
    $table->foreign('company_id')->references('id')->on('companies');
    // ...
});
```

同样，你可以用 `unsignedBigInteger()` 如果外键对应的是 `bigInteger()` 类型。

```php
Schema::create('employees', function (Blueprint $table) {
    $table->unsignedBigInteger('company_id');
});
```

## 迁移顺序

如果你想改变数据库迁移的顺序，只需要将文件按时间戳记命名， 就像 `2018_08_04_070443_create_posts_table.php` 改为 `2018_07_04_070443_create_posts_table.php` (从 `2018_08_04` 改成了 `2018_07_04`).

迁移是以字母顺序执行。

## 带时区的迁移字段

你知不知道在迁移中不止有 `timestamps()` 还有带时区的 `timestampsTz()` 。

```php
Schema::create('employees', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->string('email');
    $table->timestampsTz();
});
```

同样，还有这么些列 `dateTimeTz()` ， `timeTz()` ， `timestampTz()` ， `softDeletesTz()`。

## 数据库迁移字段类型

迁移中有一些有趣的字段类型，下面是一些示例。

```php
$table->geometry('positions');
$table->ipAddress('visitor');
$table->macAddress('device');
$table->point('position');
$table->uuid('id');
```

在 [官方文档](https://laravel.com/docs/master/migrations#creating-columns) 中你可以找到全部的字段类型列表.

## 默认时间戳

当创建迁移文件时，你可以使用带 `useCurrent()` 和 `useCurrentOnUpdate()` 可选项的 `timestamp()` 类型，这将会设置使相应字段以 `CURRENT_TIMESTAMP` 作为默认值。

```php
$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->useCurrentOnUpdate();
```

## 迁移状态

如果你想知道迁移是不是已经运行过了，不需要查看 "migrations" 表，你可以运行 `php artisan migrate:status` 命令来查看。

结果示例:

```
+------+------------------------------------------------+-------+
| Ran? | Migration                                      | Batch |
+------+------------------------------------------------+-------+
| Yes  | 2014_10_12_000000_create_users_table           | 1     |
| Yes  | 2014_10_12_100000_create_password_resets_table | 1     |
| No   | 2019_08_19_000000_create_failed_jobs_table     |       |
+------+------------------------------------------------+-------+
```

## 创建带空格的迁移

当你打入 `make:migration` 命令，你不 “必须” 在不同部分间使用下划线 \_ 进行分隔，比如 `create_transactions_table` 。你可以把名字用引号引起来并把下划线换成空格。

```php
// This works
php artisan make:migration create_transactions_table

// But this works too
php artisan make:migration "create transactions table"
```

Source: [Steve O on Twitter](https://twitter.com/stephenoldham/status/1353647972991578120)

## 在另一列的后面创建一列

> 注意：仅 MySQL 可用

如果你要在已经存在的表里增加一个新列，这个列不 “必须” 成为最后一列，你可以指定这个列创建在哪个列的后面

```php
Schema::table('users', function (Blueprint $table) {
    $table->string('phone')->after('email');
});
```

如果你要在已经存在的表里增加一个新列，这个列不 “必须” 成为最后一列，你也可以指定这个列创建在哪个列的前面：

```php
Schema::table('users', function (Blueprint $table) {
    $table->string('phone')->before('created_at');
});
```

如果你让创建的列排在表中的第一个，那么可以使用 `first` 方法。

```php
Schema::table('users', function (Blueprint $table) {
    $table->string('uuid')->first();
});
```

## 为已经存在的表生成迁移文件

如果你要为已经存的表生成迁移文件，而且你想让 Lavarel 来为你生成 Schema::table () 代码，那么，在命令后面加入 "\_in\_xxxxx\_table" 或"\_to\_xxxxx\_table"，或者指明 "--table" 参数。 `php artisan make:migration change_fields_products_table` generates empty class

```php
class ChangeFieldsProductsTable extends Migration
{
    public function up()
    {
        //
    }
}
```

但是，加入 `in_xxxxx_table` `php artisan make:migration change_fields_in_products_table` 生成了填好了 `Schemma::table()` 的类。

```php
class ChangeFieldsProductsTable extends Migration
{
    public function up()
    {
        Schema::table('products', function (Blueprint $table) {
            //
        })
    };
}
```

同样，你可以指明 `--table` 参数 `php artisan make:migration whatever_you_want --table=products`

```php
class WhateverYouWant extends Migration
{
    public function up()
    {
        Schema::table('products', function (Blueprint $table) {
            //
        })
    };
}
```

## 执行迁移前先输出 SQL 语句

当输入 migrate --pretend 命令，你可以得到将在终端中执行的 SQL 查询。如果有需要的话调试 SQL 的方法，这是个很有趣的方法。

```php
// Artisan command
php artisan migrate --pretend
```

由 [@zarpelon](https://github.com/zarpelon) 提供

## 匿名迁移

`Laravel` 团队发布了 `Laravel 8.37` 版本 支持匿名迁移，解决了迁移命名冲突的问题。

这个问题的核心是 如果多个迁移有相同的类名 当尝试重新创建数据库时可能会导致问题

以下是一个来自 `pr` 的例子

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

return new class extends Migration {
    public function up(
    {
        Schema::table('people', function (Blueprint $table) {
            $table->string('first_name')->nullable();
        });
    }

    public function down()
    {
        Schema::table('people', function (Blueprint $table) {
            $table->dropColumn('first_name');
        });
    }
};
```

由 [@nicksdot](https://twitter.com/nicksdot/status/1432340806275198978) 提供

## 给迁移添加注释

在迁移中你可以给字段添加 `comment` 提供有用的信息。

如果数据库被其他开发者管理,他们在任何操作之前可以看这些表结构的注释。

```php
$table->unsignedInteger('interval')
    ->index()
    ->comment('This column is used for indexing.')   
```

由 [@Zubairmohsin33](https://twitter.com/Zubairmohsin33/status/1442345998790107137) 提供

## 表名表字段检测

你可以使用 `hasTable` 和 `hasColumn` 方法检测表或字段是否存在。

```php
if (Schema::hasTable('users')) {
    // The "users" table exists...
}
if (Schema::hasColumn('users', 'email')) {
    // The "users" table exists and has an "email" column...
}
```

由 [@dipeshsukhia](https://github.com/dipeshsukhia) 提供

## 使用 After 方法中对列进行分组

在你的迁移中，可以使用 after 方法在另一列后面添加多个列。

```php
Schema::table('uers', function (Blueprint $table) {
    $table->after('password', function ($table) {
        $table->string('address_line1');
        $table->string('address_line2');
        $table->string('city');
    });
});
```

由 [@ncosmeescobedo](https://twitter.com/cosmeescobedo/status/1512233993176973314) 提供


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tips.laradoc.cn/migrations.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
