官方文档:https://laravel.com/docs/5.5/migrations
一,生成迁移
php artisan make:migration create_表名(复数)_table
例如新建一个admins表
php artisan make:migration create_admins_table
注意make:migration有1个必写的参数name, 3个可选的选项 –create,–tabel,–path
- –path是指定迁移文件生成的位置,默认是放在 应用根目录/database/migrations下面,如果指定了–path=x/y/x,就会在 应用根目录/x/y/z下面生成迁移文件,注意的是得保证该目录已存在,否则会报错
- 新建表时,name的写法可以是 create_表名_table,这种写法,后面的create可以省略,否则不能省,如make:migration wang –create=members
- 选项前有两个减号–,新手易写掉一个
- –create=表名,新建一个表,表名一般全为小写字母,复数形式
- –table=表名,修改现成的表
- –create与–tabel是2选1
- 在命令行自动生成的迁移文件只能是在当前项目下,如果想在项目外如vendor/包/模块中生成迁移文件,得手工编写,或自动生成后拷贝到指定地方,但要注意的是模块中的服务提供商中得写publish方法
- 生成的迁移文件名格式是 yyyy_mm_dd_His_name.php,文件中类名是将name写在大驼峰的格式,如name为create_admins_table变成
class CreateAdminsTable extends Migration
- 生成的文件名是可以修改的,用来调整顺序,系统的排序是
asort(名字名组成的数组,SORT_REGULAR );
以升序的方式排列的,所以改名时要注意- 没有运行migrate之前,迁移文件是可以手工删除和改名,修改内容的
二,编辑迁移
up是migrate时执行的方法
down是migrate:rollback,migrate:reset,migrate:fresh,migrate:refresh时会执行的方法
Facade(有人翻译成门面,我觉得翻译成表面比较合适些) Schema::方法实际上是执行\Illuminate\Database\Schema\MySqlBuilder
的方法,分下面几种判断的有 hasTable,hasColumn,hasColumns
读取的有 getAllTables,getColumnListing,getColumnType,getConnection
设置的有 setConnection,blueprintResolver
删除的有 dropAllTables
操作的有 rename,enableForeignKeyConstraints,disableForeignKeyConstraints
* 迁移常用有 create,table,drop,dropIfExists *Blueprint(翻译成蓝图),其实就是代表一个数据库中的表,它的方法主要有2种,一是针对命令commands的方法,另是针对列columns的方法,命令和列都是一个流Fluent对象,处理命令的方法不多,主要熟悉的是处理列的方法,下面是针对Mysql数据的一些列方法和修饰器
class CreateArticleTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('article', function (Blueprint $table) { $table->increments('id')->comment('文章ID'); $table->string('title',50)->unique()->comment('文章标题'); $table->string('author')->comment('文章作者'); $table->longText('content')->comment('文章内容'); $table->timestamp('add_time')->comment('添加时间'); // $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('article'); } }
字符串类型
分类 | 方法 | mysql类型 | 使用说明 |
---|---|---|---|
字符串01 | char(列名, 长度 = null) | char | 定长字符串 |
字符串02 | string(列名, 长度 = null) | varchar | 长度可变字符串 |
字符串03 | text(列名) | text | 支持2^16-1个字节,相当于2.1万个汉字 |
字符串04 | mediumText(列名) | mediutext | 支持2^24-1个字节,相当于560万个汉字 |
字符串05 | longText(列名) | longtext | 支持2^32-1个字节,相当于14亿个汉字 |
实现01: | rememberToken() | varchar(100) | string(‘remember_token’, 100)->nullable() |
实现02: | uuid(列名) | char(36) | |
实现03: | ipAddress(列名) | varchar(45) | |
实现04: | macAddress(列名) | varchar(17) |
说明1: string长度指的是字符长度,不是字节,最大支持2^8-1=255个字符,1个数字,字母,汉字都是算一个字符,string(‘name’,25)表示可以储存25个汉字
说明2: text长度指的是字节,
说明3: char适合等长密码,邮编等,默认为…Builder::$defaultStringLength,这个值是可以在服务提供商中修改的
说明4: text与string有些不一样,在utf8编码下,一个汉字相当于3个字节,最大支持21845个汉字,多一个字就会报错
整数类型
分类 | 方法 | mysql类型 | 使用说明 |
---|---|---|---|
整数01 | 参数(列名, 自增长 = false, 无符号 = false) tinyIntegert 和 unsignedTinyInteger | tinyint | 占1个字节,长度2^8 |
整数02 | integer 和 unsignedInteger | int | 占2个字节,长度2^16 |
整数03 | smallInteger 和 unsignedSmallInteger | smallint | 占3个字节,长度2^24 |
整数04 | mediumInteger 和 unsignedMediumInteger | mediumint | 占4个字节,长度 2^32 |
整数05 | bigInteger 和 unsignedBigInteger | bigint | 占8个字节,长度2^63 |
自增长列01 | increments(列名) unsignedInteger(列名, true) | ||
自增长列02 | tinyIncrements(列名) unsignedTinyInteger(列名, true) | ||
自增长列03 | smallIncrements(列名) unsignedSmallInteger(列名, true) | ||
自增长列04 | mediumIncrements(列名) unsignedMediumInteger(列名, true) | ||
自增长列05 | bigIncrements(列名) unsignedBigInteger(列名, true) | ||
真假 | boolean($column) | tinyint(1) |
说明1: 整数类型都指定不了长度,也指定不了zerofill,不过这没有关系,因为整数实际存储的长度与指定的长度没有关系,只是显示的长度而已
小数类型
分类 | 方法 | mysql类型 | 使用说明 |
---|---|---|---|
单精度浮点数 | float(column,column,total = 8, $places = 2) | 弃用 | 单精度必须要指定M和D |
双精度浮点数 | double(column,column,total = null, $places = null) | double(M,D) 或double | |
正负定点数 | decimal(column,column,total = 8, $places = 2) unsignedDecimal | decimal(M,D) | 精度和标度必须指定,默认为(8,2) |
说明1: float是单精度浮点数,double是双精度浮点数,decimal是定点数
说明2: float占4个字节,double占8个字节
说明3: 这3个类型也可以理解为小数
说明4: 浮点数存在误差问题,定点数精确,对货币等对精度敏感的数据,应该用定点数表示或存储;
说明5: 编程中,如果用到浮点数,要特别注意误差问题,并尽量避免做浮点数比较;
说明6: FLOAT(M,D),DOUBLE(M,D)。表示共M位数,小数点前面为M-D位,小数点后面为D位
说明7: decimal在mysql内存是以字符串存储的
日期时间
分类 | 方法 | mysql类型 | 使用说明 |
---|---|---|---|
日期 | date($column) | date | |
时间 | time($column) | time | |
时间 | timeTz($column) | time | |
日期时间 | dateTime(column,column,precision = 0) | datetime(精度) datetime | |
日期时间 | dateTimeTz(column,column,precision = 0) | datetime | |
时间戳 | timestamp(column,column,precision = 0) | timestamp | 用使用useCurrent使用当前时间 |
时间戳 | timestampTz(column,column,precision = 0) | timestamp | |
时间戳实现 | timestamps(precision=0)...||timestamp(′createdat′,precision=0)...||timestamp(′createdat′,precision)->nullable(); timestamp(‘updated_at’, $precision)->nullable(); | ||
时间戳实现 | timestampsTz(precision=0)...||timestampTz(′createdat′,precision=0)...||timestampTz(′createdat′,precision)->nullable(); timestampTz(‘updated_at’, $precision)->nullable(); | ||
时间戳实现 | nullableTimestamps($precision = 0) | 是timestamps的别名 | |
时间戳实现 | softDeletes(列名 = ‘deleted_at’,精度 = 0) | ||
时间戳实现 | softDeletesTz($precision = 0) |
说明01: datetime不支持取默认值now(),版本5.6之后的可以默认值CURRENT_TIMESTAMP,它会取当前时间,并转为2017-11-01 23:25:45类的格式,但这种情况不能指定精度,另处写法是new \Illuminate\Database\Query\Expression(‘CURRENT_TIMESTAMP’)才能使用Mysql中的常量
说明02: timestamp(‘列名’,精度),如果指定了精度就不能使用修饰->useCurrent(),框架源代码此处是一个bug,等修正, 只有不指定精度时才可能使用useCurrent
说明03: datetime(3)意思是保留3为毫秒数,timestamp(‘login’,3);的结果如2017-11-02 02:08:34.864,也是保留3位毫秒
说明04: TZ是系统时区的意思,但实际使用中使用非Tz格式就行
说明05: 未提供year的方法,可能是year的范围太小的原因舍弃了,可以使用date获取
日期类型 | 存储空间 | 日期格式 | 日期范围 |
---|---|---|---|
datetime | 8 bytes | YYYY-MM-DD HH:MM:SS | 1000-01-01 00:00:00 至 9999-12-31 23:59:59 |
timestamp | 4 bytes | YYYY-MM-DD HH:MM:SS | 1970-01-01 00:00:01 至 2038 |
date | 3 bytes | YYYY-MM-DD | 1000-01-01 至 9999-12-31 |
year | 1 bytes | YYYY | 1901 至 2155 |
其它
分类 | 方法 | mysql类型 | 使用说明 |
---|---|---|---|
枚举 | enum($column, [‘市场部’,’设计部’,’总裁办’]) | 生成enum(‘市场部’,’设计部’,’总裁办’) | |
json($column) | json | 这是5.7.7后才有的功能 | |
jsonb($column) | json | 这是5.7.7后才有的功能 |
说明:json很好用,但要看mysql版本支不支持
索引
添加索引的命令是
indexCommand(type,type,columns, index,index,algorithm = null)
删除索引的命令是
dropIndexCommand(command,command,type, $index)
5种索引的单独命令
命令 | 实际 |
---|---|
primary | indexCommand(‘primary’, columns,columns,name, $algorithm) |
unique | indexCommand(‘unique’, columns,columns,name, $algorithm) |
index | indexCommand(‘index’, columns,columns,name, $algorithm) |
spatialIndex | indexCommand(‘spatialIndex’, columns,columns,name) |
foreign | indexCommand(‘foreign’, columns,columns,name) |
dropIndex | dropIndexCommand(‘dropIndex’, ‘index’, $index) |
dropPrimary | dropIndexCommand(‘dropPrimary’, ‘primary’, $index) |
dropUnique | dropIndexCommand(‘dropUnique’, ‘unique’, $index) |
dropForeign | dropIndexCommand(‘dropForeign’, ‘foreign’, $index) |
说明:如果将某单列定义为某种索引,可以直接按修饰命令的方式定义,如 $table->string(‘name’)->unique();但这种方式不适合外键
熟悉迁移命令
-
- 生成迁移文件
php artisan make:migration create_wang04_table --path=database/migrations2
php artisan make:migration create_wang05_table --path=database/migrations2
- 运行迁移,凡在指定路径下有的文件名,没有出现在仓库表的migration字段中的,就会执行
php artisan migrate --database=mysql2 --path=database/migrations2
- 撤销上一步迁移,只一步啊,上一次migrate有多少变动,如生成5张表,这一次会全部撤销
php artisan migrate:rollback --database=mysql2 --path=database/migrations2
- 撤销全部,清空仓库表,除了仓库表外,所有的表都删除
php artisan migrate:reset --database=mysql2 --path=database/migrations2
- 删除所有的表,再重新运行一个迁移,它的效率比6要高
php artisan migrate:fresh --database=mysql2 --path=database/migrations2
- 全部撤销并重新运行迁移,与fresh的差别是它是一步一步的撤销,原来假设有78步,那么就一步一步撤,再一步一步运行,它俩有一个共同点是,最后只算一批,也就是所有的迁移是一批,仓库表中的batch值全部为1
php artisan migrate:refresh --database=mysql2 --path=database/migrations2
- 显示当前迁移的状态
php artisan migrate:status --database=mysql2 --path=database/migrations2
- 生成迁移文件
migate命令会将没有运行过的迁移文件运行,有几个执行几个 ,不用担心会把之前有数据的表重新构建!
migrate:rollback 只会撤销最后一批,如上面会撤销第3批生成的两个表
migrate:install 用来生成仓库表,不用执行,系统会自动执行,且只会执行一次,该表不会被撤销
migrate:status 显示哪些迁移文件还未运行,N表示还未运行
migrate:reset Rollback all database migrations
migrate:fresh 会删除所有已经生成的表,并重新运行所有的迁移
migrate:refresh Reset and re-run all migrations
Ran? | Migration |
---|---|
Y | 2017_11_02_091523_wang01 |
Y | 2017_11_02_103519_create_json_table |
Y | 2017_11_02_142016_create_wang01_table |
Y | 2017_11_02_142040_create_wang02_table |
Y | 2017_11_02_142103_create_wang03_table |
Y | 2017_11_02_142928_create_wang04_table |
N | 2017_11_02_143043_create_wang05_table |
N | 2017_11_02_143104_create_wang06_table |
迁移文件发布
数据迁移文件一般与模块放在一起,比如你开发了一个模块,有自己的数据表,当别人使用你的模块时,得先将你的数据迁移文件拷贝到应用的指定文件夹下。这样很不方便,所以得在模块的服务提供商文件中写好发布方法
<?php
namespace Wang\Providers;
use Illuminate\Support\ServiceProvider; class ModuleServiceProvider extends ServiceProvider{ protected $defer = false; public function boot(){ $this->publishMigrations(); } private function publishMigrations() { $this->publishes([__DIR__ . '/../../migrations/' => base_path('database/migrations2')], 'migrations'); } }
在使用的应用中,只要使用 php artisan vendor:publish 就会将模块中的迁移文件拷贝到应用下相应目录中
如何给应用外模块生成迁移文件?
答:一般的做法是,先在当前应用中生成,经测试没问题后,可直接拷贝到模块中
2)修改已创建的数据表字段(make:migration add)
想要修改已创建的数据表,不能直接改原来的 migrate 文件,要新建一个迁移文件,命令如下:
php artisan make:migration add_description_to_articles_table --table=articles
php artisan make:migration change_description_on_articles_table --table=articles
PS:其实migrate 文件的名字是怎么的都无所谓的,主要是里面的内容,不过名字都是要尽量写规范一点,让别人看到名字就知道是什么意思
添加或修改字段的操作是非常相似的,后者只是多了一个change()方法
新增字段:
public function up() { Schema::table('articles', function (Blueprint $table) { $table->string('description')->nullable()->after('title'); }); } public function down() { Schema::table('articles', function (Blueprint $table) { $table->dropColumn('description'); }); }
修改字段:
public function up() { Schema::table('articles', function (Blueprint $table) { $table->string('description', 200)->change(); }); } public function down() { Schema::table('articles', function (Blueprint $table) { // }); }
运行 php artisan migrate 命令后,即可生效