由淺入深laravel教程第3課:玩轉數據遷移migration(超詳細版)

補充上節課:配置虛擬主機
不用修改nginx的配置文件,減小學習成本,只要在homestead.yamlhost文件兩個文件中作很小的改動就行php

  • D:\03www2018\homestead\Homestead.yaml
map: myblog.app
    to: /home/vagrant/abcde/study/myblog/public
  • C:\Windows\System32\drivers\etc\hosts
192.168.10.10 www.myblog.app
  • D:\03www2018\study\myblog\config\app.php
'timezone' => 'Asia/Shanghai',

D:03www2018studymyblog.env.homehtml

DB_PREFIX=study_
  • D:\03www2018\study\myblog\config\database.php
'migrations' => 'migrations2017',
'prefix' => env('DB_PREFIX', ''),

一:數據庫配置

新建鏈接和數據庫

在navicat for mysql中新建鏈接,用戶名 homestead,密碼 secret,新建數據庫myblog,字符集爲 utf8mb4 -- UTF-8 Unicode,規則排序爲 utf8mb4_general_ci

新增長一個用戶

GRANT ALL PRIVILEGES ON myblog.* TO daqi@localhost IDENTIFIED BY 'daqi168' WITH GRANT OPTION;

給應用指定開發環境

有5個地方能夠指定開發環境[咱們這裏使用第1種方法或第2種方法]mysql

  • 在homestead.yaml中
  • 在入口文件的最開始加上 putenv("APP_ENV=home");
  • 修改web服務器的配置文件,如nginx配置文件中加上 env APP_ENV=home;
    apache配置文件中加上SetEnv APP_ENV home
  • 在.htaccess中加上
  • php主配置文件php-fpm.conf來設置

修改homestead.yaml加下nginx

variables:
       - key: 'APP_ENV'
         value: 'home'
       - key: 'APP_DEBUG'
         value: 'true'

編輯應用配置文件.env.home

先生成應用的keylaravel

vagrant@homestead:~/abcde/study/myblog$ php artisan key:generate
Application key [base64:s6Rhb/LhTYIpjXi3x+tN9Yon/iBavjnxO4bjXmrYq1g=] set successfully.
將生成的key放在配置文件.env.home中APP_KEY
有關base64的詳細瞭解參考: 阮一峯的base64筆記
每一個laravel必須得生成一個key,它是在加密模塊中必需要用到的,
APP_NAME=個人博客
APP_ENV=local
APP_KEY= base64:s6Rhb/LhTYIpjXi3x+tN9Yon/iBavjnxO4bjXmrYq1g=
APP_DEBUG=true
APP_LOG_LEVEL=debug
APP_URL=http://localhost

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=myblog
DB_USERNAME=daqi
DB_PASSWORD=daqi168
DB_PREFIX=study_ //本身加

D:\03www2018\study\myblog\config\database.php中改web

'prefix' => env('DB_PREFIX', ''),
'migrations' => 'migrations2017',

安裝調試文件(可選)

vagrant@homestead:~/abcde/study/myblog$ composer require advance100/helper

二:生成第一個遷移文件

官方文檔參考
先了解一下有關migrate的全部命令sql

make:migration 新建一個遷移文件
migrate 運行數據庫遷移,這個是安裝軟件時執行的
migrate:fresh 會刪除全部已經生成的表,並從新運行全部的遷移
migrate:install 新建一個遷移倉庫,會在homestead數據庫中生成一個表migrations
migrate:refresh Reset and re-run all migrations
migrate:reset Rollback all database migrations
migrate:rollback 只回滾最後一條遷移
migrate:status 顯示每條遷移的狀態

make:migration

參考: \Illuminate\Database\Console\Migrations\MigrateMakeCommandshell

  • 文件名格式爲: date('Y_m_d_His')的值
  • 文件的保存路徑:默認爲基本路徑/database/migrations/下面,若是指定了--path參數就是基本路徑/+指定路徑

問題來了?若是我想放在其它路徑,如vendor下面的某個模塊下面如作操做?
答:這要用到 php artisan vendor:publish數據庫

以新建一個用戶權限管理爲例,建如下幾個表apache

  • admins
  • roles
  • permissons
  • role_user
  • permisson_user

生成建表admins的遷移文件

vagrant@homestead:~/abcde/study/myblog$ php artisan make:migration create_admins_table
Created Migration: 2017_10_31_231348_create_admins_table

注意make:migration有1個必寫的參數name, 3個可選的選項 --create,--tabel,--path

  1. --path是指定遷移文件生成的位置,默認是放在 應用根目錄/database/migrations下面,若是指定了--path=x/y/x,就會在 應用根目錄/x/y/z下面生成遷移文件,注意的是得保證該目錄已存在,不然會報錯
  2. 新建表時,name的寫法能夠是 create_表名_table,這種寫法,選項--create能夠省略,不然不能省,如make:migration wang --create=members
  3. 選項前有兩個減號--,新手易寫掉一個
  4. --create=表名,新建一個表,表名通常全爲小寫字母,複數形式
  5. --table=表名,修改現成的表
  6. --create--table是2選1
  7. 在命令行自動生成的遷移文件只能是在當前項目下,若是想在項目外如vendor/包/模塊中生成遷移文件,得手工編寫,或自動生成後拷貝到指定地方,但要注意的是模塊中的服務提供商中得寫publish方法
  8. 生成的遷移文件名格式是 yyyy_mm_dd_His_名字.php,文件中類名是將name寫在大駝峯的格式,如name爲create_admins_table變成class CreateAdminsTable extends Migration
  9. 生成的文件名是能夠修改的,用來調整順序,系統的排序是asort(名字名組成的數組,SORT_REGULAR ); 以升序的方式排列的,因此更名時要注意
  10. 沒有運行migrate以前,遷移文件是能夠手工刪除和更名,修改內容的

按上面生成另外幾個遷移文件

php artisan make:migration create_roles_table
php artisan make:migration create_permissions_table
php artisan make:migration create_role_user_table
php artisan make:migration create_permission_role_table

三:編輯遷移文件

up是migrate時執行的方法
downmigrate:rollback,migrate:reset,migrate:fresh,migrate:refresh時會執行的方法
Facade(有人翻譯成門面,我以爲翻譯成表面比較合適些) Schema::方法其實是執行 \Illuminate\Database\Schema\MySqlBuilder的方法,分下面幾種

判斷的有 hasTable, hasColumn, hasColumns
讀取的有 getAllTables,g etColumnListing, getColumnType, getConnection
設置的有 setConnection, blueprintResolver
刪除的有 dropAllTables
操做的有 rename, enableForeignKeyConstraints, disableForeignKeyConstraints

遷移經常使用有 Schema::create,Schema::table,Schema::drop,Schema::dropIfExists

Blueprint(翻譯成藍圖),其實就是表明一個數據庫中的表,它的方法主要有2種,一是針對命令commands的方法,另是針對列columns的方法,命令和列都是一個流Fluent對象,處理命令的方法很少,主要熟悉的是處理列的方法,下面是針對Mysql數據的一些列方法和修飾器
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateAdminsTable extends Migration{
    public function up(){
        Schema::create('admins', function (Blueprint $table) {       
            $table->charset='utf8mb4';
            $table->collation='utf8mb4_unicode_ci';
            $table->engine='innodb';
            //$table->temporary();
            // 上面四條是演示能夠單獨給某個表指定以上屬性
            $table->increments('id');
            $table->string('name')->comment("用戶名");
            $table->string('email')->unique()->comment("郵箱必須惟一"); //unique()爲索引命令,comment爲修飾
            $table->string('password',60)->comment("密碼最長爲60個字節");
            $table->rememberToken()->comment("口令");
            $table->text('description')->nullable()->comment("管理員說明");
            $table->timestamps();
        });
    }

    public function down(){
        Schema::dropIfExists('admins');
    }
}

3.1 列Columns

  • getColumns()獲取藍圖Blueprint的全部列,每一列也是一個流Fluent對象,流對象中有type和name兩個必須指定
  • addColumn($type, $name, array $parameters = []) 重點講
  • removeColumn($name)
  • getAddedColumns() 獲取全部新加的列
  • getChangedColumns() 獲取全部改動了的列

3.1.1 字符串類型

分類 方法 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個漢字,多一個字就會報錯

3.1.2 整數類型

分類 方法 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,不過這沒有關係,由於整數實際存儲的長度與指定的長度沒有關係,只是顯示的長度而已

3.1.3 小數類型

分類 方法 mysql類型 使用說明
單精度浮點數 float($column, $total = 8, $places = 2) 棄用 單精度必需要指定M和D
雙精度浮點數 double($column, $total = null, $places = null) double(M,D) 或double
正負定點數 decimal($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內存是以字符串存儲的

3.1.4 日期時間

分類 方法 mysql類型 使用說明
日期 date($column) date
時間 time($column) time
時間 timeTz($column) time
日期時間 dateTime($column, $precision = 0) datetime(精度)
datetime
日期時間 dateTimeTz($column, $precision = 0) datetime
時間戳 timestamp($column, $precision = 0) timestamp 用使用useCurrent使用當前時間
時間戳 timestampTz($column, $precision = 0) timestamp
時間戳實現 timestamps($precision = 0){...} timestamp('created_at', $precision)->nullable();<br>timestamp('updated_at', $precision)->nullable();
時間戳實現 timestampsTz($precision = 0){...} timestampTz('created_at', $precision)->nullable();<br>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 IlluminateDatabaseQueryExpression('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

3.1.5 其它

分類 方法 mysql類型 使用說明
枚舉 enum($column, ['市場部','設計部','總裁辦']) 生成enum('市場部','設計部','總裁辦')
json($column) json 這是5.7.7後纔有的功能
jsonb($column) json 這是5.7.7後纔有的功能
二進制 binary($column) blob
  • 說明:json很好用,但要看mysql版本支不支持
  • 說明: 沒有mediumbloblongblob,這樣儲存圖片聲音等文件沒有辦法,解決辦法是在
Schema::create("member", function($table) {
    // 這裏能夠放SchemaBuilder支持的各類方法
});
DB::statement("ALTER TABLE member ADD imagedata MEDIUMBLOB");

3.1.6 空間

MySQL 5.7 GIS特性

方法 mysql類型 使用說明
geometry($column) geometry
point($column) point
lineString($column) linestring
polygon($column) polygon
geometryCollection($column) geometrycollection
multiPoint($column) multipoint
multiLineString($column) multilinestring
multiPolygon($column) multipolygon

3.1.7 綜合實現: 生成索引

morphs($name, $indexName = null){
    $this->unsignedInteger("{$name}_id");
    $this->string("{$name}_type");
    $this->index(["{$name}_id", "{$name}_type"], $indexName);
}

nullableMorphs($name, $indexName = null){
    $this->unsignedInteger("{$name}_id")->nullable();
    $this->string("{$name}_type")->nullable();
    $this->index(["{$name}_id", "{$name}_type"], $indexName);
}

3.2: Blueprint中的列的修飾符

Nullable,Default,Comment,Unsigned,VirtualAs,StoredAs,Charset,Collate,Increment,After,First

3.3 索引

添加索引的命令是
indexCommand($type, $columns, $index, $algorithm = null)
刪除索引的命令是
dropIndexCommand($command, $type, $index)

5種索引的單獨命令

命令 實際
primary indexCommand('primary', $columns, $name, $algorithm)
unique indexCommand('unique', $columns, $name, $algorithm)
index indexCommand('index', $columns, $name, $algorithm)
spatialIndex indexCommand('spatialIndex', $columns, $name)
foreign indexCommand('foreign', $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();但這種方式不適合外鍵

3.4 命令

每個命令都是一個流(Flent)對象,流對象中name必須指定,好比 create()就是在commands增長一個name爲create的流對象
處理命令的有: getCommands獲取全部的命令,addCommand,createCommand
判斷是否有create命令creating
對錶create,drop,dropIfExists,rename
對錶中的列,dropColumn,renameColumn

四: 熟悉遷移命令

  1. 生成遷移文件

php artisan make:migration create_wang04_table --path=database/migrations2
php artisan make:migration create_wang05_table --path=database/migrations2

  1. 運行遷移,凡在指定路徑下有的文件名,沒有出如今倉庫表的migration字段中的,就會執行
    php artisan migrate --database=mysql2 --path=database/migrations2
  2. 撤銷上一步遷移,只一步啊,上一次migrate有多少變更,如生成5張表,這一次會所有撤銷

php artisan migrate:rollback --database=mysql2 --path=database/migrations2

  1. 撤銷所有,清空倉庫表,除了倉庫表外,全部的表都刪除

php artisan migrate:reset --database=mysql2 --path=database/migrations2

  1. 刪除全部的表,再從新運行一個遷移,它的效率比6要高

php artisan migrate:fresh --database=mysql2 --path=database/migrations2

  1. 所有撤銷並從新運行遷移,與fresh的差異是它是一步一步的撤銷,原來假設有78步,那麼就一步一步撤,再一步一步運行,它倆有一個共同點是,最後只算一批,也就是全部的遷移是一批,倉庫表中的batch值所有爲1

php artisan migrate:refresh --database=mysql2 --path=database/migrations2

  1. 顯示當前遷移的狀態

php artisan migrate:status --database=mysql2 --path=database/migrations2

id migration batch
6 2017_11_02_091523_wang01 1
7 2017_11_02_103519_create_json_table 1
8 2017_11_02_142016_create_wang01_table 1
9 2017_11_02_142040_create_wang02_table 1
10 2017_11_02_142103_create_wang03_table 1
11 2017_11_02_142928_create_wang04_table 2
12 2017_11_02_143043_create_wang05_table 3
13 2017_11_02_143104_create_wang06_table 3
  • 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

五: 遷移文件發佈

數據遷移文件通常與模塊放在一塊兒,好比你開發了一個模塊,有本身的數據表,當別人使用你的模塊時,得先將你的數據遷移文件拷貝到應用的指定文件夾下。這樣很不方便,因此得在模塊的服務提供商文件中寫好發佈方法

六: 多數據庫版

6.1 新建數據庫laravel_study

字符集utf8 -- UTF-8 Unicode,排序規則:utf8_general_ci

6.2 配置第二個數據庫

D:\03www2018\study\myblog\config\database.php增長以下

//第2個數據庫鏈接
        'mysql2' => [
            'driver'    => 'mysql',
            'host'      => '127.0.0.1',
            'database'  => 'laravel_study',
            'username'  => 'zhangxueyou',
            'password'  => 'liudehua',
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix'    => '',
        ],

6.3 新增長一個用戶

GRANT ALL PRIVILEGES ON study_laravel.* TO zhangxueyou@localhost IDENTIFIED BY 'liudehua' WITH GRANT OPTION;

6.4 重啓mysql

$ sudo service mysql restart

6.5 新建遷移文件

先建好文件夾migrations2
$ php artisan make:migration wang01 --create=study01 --path=database/migrations2

6.6 編輯遷移文件

<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class Wang01 extends Migration{

    public function up(){
        Schema::connection('mysql2')->create('study01', function (Blueprint $table) {
            $table->increments('id');
            $table->string('username',25);
            $table->dateTime('mydatetime')->default(new \Illuminate\Database\Query\Expression('CURRENT_TIMESTAMP'));
            $table->timestamp('register_time')->useCurrent();
            //$table->timestamp('register_time',3);
            $table->timestamps();
        });
    }
    public function down() {
        Schema::connection('mysql2')->dropIfExists('study01');
    }
}
  • 上面要注意默認值爲CURRENT_TIMESTAMP的寫法,若是不這樣寫,系統爲了安全會加上單引號,另外該msyql常量只在mysql版本高於5.6纔有

6.7 遷移和回滾

vagrant@homestead:~/abcde/study/myblog$ php artisan migrate --database=mysql2 --path=database/migrations2
vagrant@homestead:~/abcde/study/myblog$ php artisan migrate:rollback --database=mysql2 --path=database/migrations2
相關文章
相關標籤/搜索