很多人可能在學(xué)習(xí)Laravel框架的時候,對Laravel的數(shù)據(jù)庫遷移(以下簡稱Migrations)存在著疑惑:
1. 什么是 Migrations?
2. 為什么要用 Migrations?
3. Migrations 到底方便在哪里?
好了,抱著這些問題,我們今天就一起來學(xué)習(xí)Migrations。
什么是 Migrations?
我們先來看一下Laravel官方文檔怎么寫的:
Migrations are like version control for your database, allowing your team to easily modify and share the application's database schema. Migrations are typically paired with Laravel's schema builder to easily build your application's database schema. If you have ever had to tell a teammate to manually add a column to their local database schema, you've faced the problem that database migrations solve.
簡單概括起來,就是我們可以將Migrations看作一種數(shù)據(jù)庫的VCS(Version Control System),即版本控制系統(tǒng)。
可以通過Laravel的artisan命令快速創(chuàng)建、修改或還原數(shù)據(jù)庫結(jié)構(gòu)。
為什么要用 Migrations?
使用Migrations可以有效地對數(shù)據(jù)庫進(jìn)行版本控制,并且遵從了Single Responsibility Principle(單一職責(zé)原則),更加方便數(shù)據(jù)庫的操控。
舉個例子來說,假設(shè)我們已經(jīng)設(shè)計并創(chuàng)建好了數(shù)據(jù)庫,數(shù)據(jù)已經(jīng)填充進(jìn)數(shù)據(jù)庫了,現(xiàn)在我們發(fā)現(xiàn)需要在其中一張表里增加一個名為name的欄目(column),需要在另一張表中將author欄目的名字改為user,那么我現(xiàn)在進(jìn)入數(shù)據(jù)庫里,進(jìn)行了操作。剛剛操作完,公司老板突然找我面談。面談完了之后,我忘記了將我在數(shù)據(jù)庫里的操作記錄下來或者告知給其他開發(fā)人員,那么隨之而來的很可能是災(zāi)難性的結(jié)果。
如果我們使用了Migrations,并且只通過Migrations進(jìn)行數(shù)據(jù)庫的操作,那么所有開發(fā)人員都可以看到數(shù)據(jù)庫進(jìn)行了哪些操作,而不會發(fā)生上述的情況。
Migrations 到底方便在哪里?
除了上述提到的版本控制功能外,我們幾乎不需要寫SQL代碼就能簡單快速地組建起數(shù)據(jù)庫結(jié)構(gòu),并且可以迅速遷移(migrate)或者回滾(Rollback),省去了大量人工操作的繁瑣。
講解完了概念,我們現(xiàn)在來看一下具體怎么使用Migrations。
要創(chuàng)建一個遷移文件,我們可以用以下artisan命令:
$ php artisan make:migration create_samples_table --create=samples
注意php artisan命令需要在項目根目錄下運(yùn)行。--create==samples這個選項表明我們想要建立一個名為samples的數(shù)據(jù)庫表,所以artisan會自動在database\migrations目錄下建立一個叫2017_03_13_061422_create_samples_table.php的文件(其中前綴是創(chuàng)建該文件的日期和時間,用于區(qū)分遷移文件的時間先后順序),并且會自動填充好Schema::create這個方法,方便我們創(chuàng)建更多的column:
?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateSamplesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('samples', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('samples');
}
}
我們看到,這個類中有up和down兩個方法。up中我們需要添加創(chuàng)建數(shù)據(jù)表的函數(shù),以及添加各個欄目的名稱及屬性。而down方法中我們需要添加在回滾該遷移文件時應(yīng)該有什么樣的結(jié)果(這里我們直接刪除這張表)。
可以看出,up和down中的操作是對應(yīng)的,在up中進(jìn)行了什么操作,down中就需要撤銷這些操作。
現(xiàn)在我們詳細(xì)來看一下up方法。我們看到,Schema::create這個方法是用來創(chuàng)建我們數(shù)據(jù)表的,在方法中,我們看到Laravel已經(jīng)為我們填充了幾個columns。
$table->increments('id')將創(chuàng)建一個名為id的column,并賦予PRIMARY KEY、UNSIGNED及AUTO INCREMENT屬性。
$table->timestamps()將創(chuàng)建created_at和updated_at兩個column(類型是DATETIME)。
注意:Laravel默認(rèn)認(rèn)為每個table都會存在一個id欄目,并且要求每個table都要有created_at和updated_at這兩個欄目。
現(xiàn)在,我們要在samples表里增加一個名為name的VARCHAR類型的欄目,該怎么做呢?
很簡單,只需要加上這行:
$table->string('name');
如果我們想限制VARCHAR的長度,可以在第二個參數(shù)中進(jìn)行注明:
$table->string('name', 100);
好了,我們暫時就只需要這些欄目?,F(xiàn)在我們已經(jīng)有了遷移文件了,怎么樣才能在數(shù)據(jù)庫里建立起我們的表呢?
很簡單,輸入
等待命令完成就可以了。
現(xiàn)在我們在數(shù)據(jù)庫里,就能看到我們的samples表了。
注意:運(yùn)行php artisan migrate之前請檢查你的.env文件中DB_DATABASE,DB_USERNAME,DB_PASSWORD 幾項配置是否正確。如果你在Homestead下進(jìn)行Laravel開發(fā),那么DB_USERNAME默認(rèn)為homestead,DB_PASSWORD默認(rèn)為secret,DB_DATABASE請根據(jù)你的項目具體填入你的數(shù)據(jù)庫名稱。
現(xiàn)在問題來了,我們突然想在samples表里,添加一個名為url的欄目,該怎么做呢?我們分情況討論。
1. 我們處于本地開發(fā)階段,數(shù)據(jù)使用種子(Seed)文件進(jìn)行填充。
對于本地開發(fā),如果想省事,可以直接在samples表的遷移文件中,添加上我們需要的欄目:
$table->string('url', 200)->nullable();
然后我們重置數(shù)據(jù)庫并做種:
$ php artisan migrate:refresh --seed
這樣就完成了。打開samples表,我們會發(fā)現(xiàn)新的欄目已經(jīng)被創(chuàng)建。
注意,php artisan migrate:refresh命令相當(dāng)于
$ php artisan migrate:reset
$ php artisan migrate
所以我們經(jīng)常會使用到。
2. 另一種情況,我們需要詳細(xì)記錄每一個數(shù)據(jù)庫操作,例如在production環(huán)境下進(jìn)行數(shù)據(jù)庫修改。
首先我們需要添加一個package:
$ composer require doctrine/dbal
要進(jìn)行表的修改必須添加以上包裹。
完成后我們需要創(chuàng)建一個新的遷移文件:
$ php artisan make:migration add_url_field_to_samples_table --table=samples
我們想要添加一個url欄目,并且讓它在name之后,我們在Schema::table函數(shù)中填入以下代碼:
?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class ModifySamplesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('samples', function (Blueprint $table) {
$table->string('url', 200)->after('name');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('samples', function (Blueprint $table) {
$table->dropColumn('url');
});
}
}
完成后,我們運(yùn)行migrate:
這樣,url就被添加進(jìn)了sample表中,并且位置處于name之后。
我們在samples表中插入了新的url欄目,那么現(xiàn)在如果我們想把name這個欄目長度限制從100修改為50,該怎么做呢?
同理,我們需要先創(chuàng)建一個migration:
$ php artisan make:migration modify_name_column_in_samples_table --table=samples
在migration文件中,我們添加以下代碼:
?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class ModifyNameColumnInSamplesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('samples', function (Blueprint $table) {
$table->string('name', 50)->change();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('samples', function (Blueprint $table) {
$table->string('name', 100)->change();
});
}
}
完成后,我們再次運(yùn)行migrate:
這樣一來就完成了欄目的修改,非常的直觀。
注意:如果我們想把某個欄目改成其他類型,可以采用以下語法
$table->text('name')->change();
完成之后,再次運(yùn)行php artisan migrate,我們就可以看到name已經(jīng)從VARCHAR變?yōu)榱薚EXT類型了。
好了,本文主要講解了Laravel框架中數(shù)據(jù)庫遷移操作的方法實(shí)例,更多關(guān)于Laravel框架的使用技巧請查看下面的相關(guān)鏈接
您可能感興趣的文章:- Laravel源碼解析之路由的使用和示例詳解
- 通過源碼解析Laravel的依賴注入
- 源碼分析 Laravel 重復(fù)執(zhí)行同一個隊列任務(wù)的原因
- Laravel 框架控制器 Controller原理與用法實(shí)例分析
- Laravel 框架路由原理與路由訪問實(shí)例分析
- 4種Windows系統(tǒng)下Laravel框架的開發(fā)環(huán)境安裝及部署方法詳解
- Laravel框架下的Contracts契約詳解
- laravel框架路由分組,中間件,命名空間,子域名,路由前綴實(shí)例分析
- laravel框架使用FormRequest進(jìn)行表單驗(yàn)證,驗(yàn)證異常返回JSON操作示例
- Laravel框架源碼解析之反射的使用詳解