最适合入门的Laravel初级教程(七)表迁移Migrations

看到这的时候我默认你已经配置好数据库了;
我们开始对数据库操作了;
但是前提是我们得有表啊;
说到数据库说到表;
做开发的小伙伴们肯定理解到过其中的苦于泪;
还是环境的问题;
每个同事都有一个自己的本地环境;
还有测试环境、生产环境;
团队合作的时候为了避免代码冲突;
以及方便记录修改历史和回退;
我们有版本控制比如说 git;
但是数据库怎么搞呢?
在远古时代;
在中小公司中;
在没有一套比较好用的管理表变动的方案的时候;
相信童鞋们多少都经历过改数据库的痛苦;
每次自己在本地增加了表;
或者修改了表字段;
都要记录下来告知其他同事;
其他每个同事都要在自己的本地修改表结构;
然后还要心惊胆战的修改测试环境和生产环境的数据库结构;
这种经历想想都痛苦;
但是自从有了 laravel ;
腰不酸了;腿不疼了;
一口气同步所有环境的表结构也不费劲了;

那 laravel 用的什么样的钙片来帮助我们的呢?
这就要说 laravel 内置了表迁移的功能;
它的作用就是提供数据库级的版本控制;
能保留表的变动记录;
可以回退到某个版本;
可以同步各个环境的表和结构;
虽然肯定是不像 git 那样强大;
但是已经可以极大的提升开发效率了;

我们来创建一个表迁移感受下;
当然这个肯定也不需要手动创建文件了;
命令行如下;

php artisan make:migration create_articles_table

articles 就是我们要创建的表名;
这里需要顺便提一嘴的是;
laravel 默认表都是复数形式;
那再顺便提一嘴;
config/database.php 文件中的 connections 的 prefix 可以设置每种数据库的表前缀;
迁移的时候不需要为每张表指定表前缀;
我们运行上面的命令后;
会在 database/migrations 目录生成一个迁移文件;

你运行的时候肯定不会跟我这个文件名一样;
因为我们很容易就发现这个文件加了时间前缀;
也就是说我是在 2018-01-06 11:29:15 创建的这个文件;
这样可以避免文件重复;
可以记录文件创建的时间;
还可以让文件按时间排序;
除了我们创建的 articles 表迁移文件;
我们还发现了 laravel 框架自带的 2014 年的 users 表和 password_resets 表;
我们是不是隐隐约约感觉到了 laravel 连用户和重置密码的功能都自带了?
这个咱们按下先不讲;
直接打开 2014_10_12_000000_create_users_table.php ;
我们来参考下它的内容;

里面有 up 和 down 2 个方法;
在 up 中我们看到了 create ;
在 down 中我们看到了 drop ;
根据这两个关键字;
我们基本可以理解这两个方法的作用了;
up 方法就是用来创建表的;
down 方法是用来删除表的;
当我们想回退的时候就是要执行 down 方法;
再来看详细的代码;

        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });

直接就读吧;
要 create 一个 users 表;
指定这个 table 的主键字段为 id ;
指定 name 字段为字符串类型;
指定 email 字段为字符串类型并且限制唯一性;
rememberToken 就是加一个记住我的字段;
这个字段不通用就不多讲;
重点要说下 timestamps ;
$table->timestamps(); 的作用是给表增加 created_at 和 updated_at;
它们的类型是 timestamps ;
laravel 插入和编辑数据的时候会自动通过这两个字段记录操作的日期时间;

这我们就发现了 laravel 的又一特点;
整个项目对于各种命名的斟酌;
很多时候我们即便不看文档;
甚至不看源代码注释;
只看方法名就能猜到作用了;
她不只是一个框架;
还是我们编程的一个范本;

参考了 users 表我们回到 2018_01_06_112915_create_articles_table.php ;
通过命令行生成文件的同时自动已经生成了下面这样的代码;

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            $table->increments('id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('articles');
    }

很明显;
laravel 默认表的主键字段名为 id ;
然后默认表有 created_at 和 updated_at 字段;
增删改查不分家;
增和改都默认有了个字段记录操作日期了;
那删怎么能没有呢?
没错;laravel 又为我们设计好了;
$table->softDeletes(); ;
这个方法就是为表增加一个 deleted_at ;
laravel 会在删除数据的时候记录操作日期;
具体到我们的文章的时候就是回收站的功能了;
我们可能会删除文章;
但是我们还希望能恢复删除的文章;
当某篇文章的 deleted_at 为 null 的时候表示正常;
当有日期的时候就表示这篇文章是在这个日期被删掉了;

我们再次回到 2018_01_06_112915_create_articles_table.php ;
文章一般是有所属的分类的;
我们用 int 类型的 category_id 表示分类的id;
并且用 unsigned 表示无符号;
用 default 设置默认值为0;
用 comment 写注释;
$table->integer('category_id')->unsigned()->default(0)->comment('分类id');;
再加一个 text 类型的文章内容字段 content ;
$table->text('content')->comment('文章内容');;
我们就设计了一个简易的文章表了;

        Schema::create('articles', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('category_id')->unsigned()->default(0)->comment('分类id');
            $table->string('title')->comment('标题');
            $table->text('content')->comment('内容');
            $table->timestamps();
            $table->softDeletes();
        });

在之前讲 artisan 的时候说过 artisan 主要2个作用;
最适合入门的laravel入门教程(四) ;
1是创建文件;
2是执行任务;
我们已经用 artisan 创建控制器和迁移了;
现在终于到了执行任务的时候了;
我们上面的迁移文件定义了表的结构;
执行迁移才会真正生成表;

php artisan migrate

执行上面的命令我们可以看到这样的提示;

这意思就是我们的迁移已经完成了;
那我们再执行一遍命令呢?
我们会看到这样的的提示;

Nothing to migrate.

嗯哼?也就是说已经成功的迁移并不会重复执行;
这是在哪控制的呢?
我们 show 下 table;

除了 laravel 自带的 users 表和 password_resets 表 ;
除了我们创建的 articles 表;
我们还发现了个 migrations 表;
我们看下这个表的内容;

我们的3个迁移文件名都在里面记录着了;
说明这个表里面存的是已经执行过的迁移的文件名;
再查看下 articles 表的结构;

perfect跟我们迁移文件中写的是一样的;
表就这么轻松的创建了;
但是再认真看会发现并没有 string 类型;
肯定的喽;因为 mysql 压根就没 string;
string 就是 varchar 了;
再但是再认真看还会发现除了 timestamp ;
其他的字段都多了个 NOT NULL ;
这个我们并没有在迁移中指定;
这里就需要解释下了;
这个 NOT NULL 是 laravel 为我们默认添加的;
那如果确实有字段想让它允许为 NULL 怎么办呢?
别担心; laravel 还有个 ->nullable();
我们这里讲了最常用的 int 、 varchar 、 text;
那更多的类型呢?
这时候就是 laravel 官方手册真正的作用了;
laravel 官方手册更适合作为一本工具书;
我们去像查字典一样去查工具书就可以了;
就像新华字典;
它并不适合用来入门学习汉语;
但适合我们去查询;

创建表的方式我们已经学会了;
除了创建表;
我们还经常需要改变表结构;
默认的 users 并没有 deleted_at 字段;
我们如果想为 用户 也增加一个类似回收站的字段怎么办呢?
我们再来创建一个表迁移文件;

php artisan make:migration add_deleted_at_to_users_table

在 add_deleted_at_to_users_table 文件中添加如下代码;

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->softDeletes();
        });
    }

up 中就是我们迁移的内容;
创建表的时候我们使用的是 Schema::create;
编辑表的时候我们使用的是 Schema::table
然后回调函数中的内容跟创建表的时候的格式是一样的;
运行迁移;

php artisan migrate


deleted_at 就这么加上了;
down 方法中就是回退的内容了;


    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('deleted_at');
        });
    }

创建表的时候 down 中是 drop 表;
添加字段的时候 down 中的自然就是 drop 字段了;
我们一直在说回退;
说 laravel 的迁移功能可以让我们回退到某个状态;
那到底是怎么回退呢?
其实也很简单同样是运行命令;
为了更深刻的理解 migrations 表的作用;
在运行回退命令前我们先看下 migrations 表的内容;

一共有4条记录;3条创建表的;1条添加字段的;
好我们来运行回退命令;

php artisan migrate:rollback

然后再来看 migrations 表和 users 表;

一切如我们所料;
migrations 表的第4条添加字段的记录没有了;
users 表的 deleted_at 字段也没了;
再回退一次就把第一次运行迁移的时候的3张表就全删了;
如果再运行迁移命令一切就又有了;

到这里创建表、删除表、添加字段、删除字段我们都会了;
最后再来讲个修改字段的;
修改字段需要借助dbal扩展包;
先来安装;

composer require doctrine/dbal

剩下的工作也很简单;
我们这里举个栗子;
文章的分类也没几个;
用 int 类型太奢侈了;
我们改成 tinyint 就足够了;
老规矩先创建一个迁移文件;

php artisan make:migration change_category_id_in_articles_table

然后在 up 中写上修改的内容即可;

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('articles', function (Blueprint $table) {
            $table->tinyInteger('category_id')->unsigned()->default(0)->comment('分类id')->change();
        });
    }

你以为我是要结束本篇文章的吗?
NO;
我是来讲另一个坑的;
如果运行上面这个迁移文件是会报错的;
因为 dbal 并不支持修改成 tinyInteger ;
为了兼容更多类型的数据库;
需要使用替代方案;
使用 boolean 类型;

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('articles', function (Blueprint $table) {
            $table->boolean('category_id')->unsigned()->default(0)->comment('分类id')->change();
        });
    }

那 down 里面就是相反的内容了;

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('articles', function (Blueprint $table) {
            $table->integer('category_id')->unsigned()->default(0)->comment('分类id')->change();
        });
    }

那顺便总结成一句话了;
up 中写需要迁移的内容;
down 中写回退的内容;

白俊遥博客
请先登录后发表评论
  • latest comments
  • 总共39条评论
白俊遥博客

fanzhaogui :Syntax error or access violation: 1071 Specified key was too long; max key length is 1000 bytes (SQL: alter table `users` add unique `users_email_unique`(`email`))本人版本laravel 5.5 在使用php artisan migrate时出现以上报错;解决:https://segmentfault.com/a/1190000008416200?utm_source=tag-newest

2019-06-28 01:00:00 回复

白俊遥博客

小雨的叶香伦 :虽然这个问题不一定常用,但是可能存在场景,修改表信息怎么实现,比如表名,表注释等?

2019-06-27 16:42:10 回复

白俊遥博客

youyou :所以,最后的boolean能把integer转成tinyint?如果要使用boolean类型呢

2019-04-08 07:21:21 回复

白俊遥博客

长安 Ꮺ¸ :我们平时存boolean也是用的tinyint吧?存个0或者1

2019-09-03 14:22:14 回复

白俊遥博客

花舞千魂殇 :这个可以 很溜 学习了

2019-02-25 11:11:59 回复

白俊遥博客

只是→路过、、、 :白哥,我是常关注您博客的,最近学laravel。的的数据库迁移命令,执行了没有反应。实在是网上也找不到办法才留言的,我在项目根目录执行php artisan make:migration create_db_test_table根本没反应,昨天我把migrations目录里的清空才有了反应创建了文件。今天执行又不行,我把里面的清空了也不行

2018-12-27 10:52:20 回复

白俊遥博客 白俊遥博客

云淡风晴 :php artisan make:migration create_db_test_table -vvv 看看有没有报错信息什么的;

2019-04-14 22:16:54 回复

白俊遥博客

光年 白俊遥博客大神级教程

2018-11-30 15:07:56 回复

白俊遥博客

逆光 :你好,给已经执行migrate的表添加新字段部分,php artisan make:migration add_deleted_at_to_users_table,可以改成php artisan make:migration add_deleted_at_to_users_table --table=users,这样会直接生成Schema::table()..这部分  只需要声明要添加的字段就可以了

2018-04-12 22:26:44 回复

白俊遥博客 白俊遥博客

云淡风晴 :你说的是对的;

2019-04-14 22:17:55 回复

白俊遥博客

安氏~ 白俊遥博客到这里我这个没怎么接触过php的人也能将laravel-bjyblog项目跑起来了

2018-01-29 10:50:22 回复

白俊遥博客

Fate :执行 php artisan migrate 的时候没报错吗

2018-10-24 09:13:00 回复

白俊遥博客

YOU :迁移文件中设置字段 无符号 无效$table->integer('category_id')->unsigned()->default(0)->comment('分类id');1

2018-01-22 11:28:07 回复

白俊遥博客

蓝瘦-香菇 :880af4d8f6bb2e89d30af6d5c7c4836a求大神破解

2018-01-20 20:44:26 回复

白俊遥博客

橘子汽水 :'or 1=1 ) #

2018-01-18 20:28:33 回复

白俊遥博客

不知不觉 :大神!求更新啊,等好久了

2018-01-16 15:49:11 回复

白俊遥博客

大雄 :路过围观,现在还在用thinkphp做博客,刚才准备发布评论的时候提示用QQ登录,然后现在回来哎,写了一大段的文字都没有了,心塞!!

2018-01-15 12:27:55 回复

白俊遥博客 白俊遥博客

云淡风晴 :多谢反馈;更新系统了;现在已经从多方面来避免此问题了;

2018-01-22 05:30:41 回复

白俊遥博客

BIG网络运营人 :http://www.cbqvt.top 瓜子个人博客        寻加友链啊!!!!

2018-01-13 00:39:29 回复

白俊遥博客

BIG网络运营人 :你的这个代码高亮, 在吗站长,你的这个代码高亮, 后台用的是什么编辑器啊后台用的是什么编辑器啊a45ecb871fd71c13b79b34a40dd06344

2018-01-12 23:35:41 回复

白俊遥博客

ェ瓜子壳壳ツ :创建QQ群及捐赠渠道

2018-01-12 20:24:22 回复

白俊遥博客

ェ瓜子壳壳ツ 白俊遥博客3a441d61f3a7226c6a7594af9d610cfe你的这个代码高亮, 后台用的是什么编辑器啊

2018-01-12 16:07:37 回复

白俊遥博客

hiwangqi :在吗站长,你的这个代码高亮, 后台用的是什么编辑器啊

2018-01-12 15:40:14 回复

白俊遥博客

不知不觉 :写的非常好!!!!期待下一章

2018-01-12 09:38:53 回复

白俊遥博客

ixingjue :威武  威武 威武

2018-01-11 16:57:39 回复

白俊遥博客

我是超酷男孩壮壮 :期待更新!!

2018-01-09 17:07:15 回复

白俊遥博客

卡卡 :期待更新

2018-01-09 14:50:39 回复

白俊遥博客

最初° :期待

2018-01-13 18:30:32 回复

白俊遥博客

脑容量不足患者 :多个回复

2018-01-19 11:19:16 回复

白俊遥博客

null :期待更多更新 但白大神也要注意身体啊

2018-01-09 10:49:01 回复

白俊遥博客 白俊遥博客

云淡风晴 :多谢哈;

2018-01-22 05:29:50 回复

白俊遥博客

残岩飞雪 :静候下集!!!,导演能否快点上映

2018-01-08 14:38:17 回复

白俊遥博客 白俊遥博客

云淡风晴 :更新了;尽量在周末凑时间写;

2018-01-22 05:29:15 回复

白俊遥博客

Tommy :另外请教一下遥神,baijunyao/thinkphp-bjyadmin 是不是不再更新和维护了?

2018-01-08 08:38:13 回复

白俊遥博客 白俊遥博客

云淡风晴 :在维护;不过很少会有功能性的更新;如果使用;建议迁移至 laravel-bjyblog

2018-01-22 05:28:52 回复

白俊遥博客

Tommy :遥神威武,关注你的博客很久了,很受益!

2018-01-08 08:36:04 回复

白俊遥博客 白俊遥博客

云淡风晴 :多谢支持;

2018-01-22 05:27:55 回复

白俊遥博客

天堂 :非常赞,后面的什么时候更新呢?

2018-01-06 23:01:30 回复

白俊遥博客 白俊遥博客

云淡风晴 :尽量做到每个周末凑时间更新;

2018-01-22 05:27:48 回复