iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 9
0
Modern Web

Laravel 6.0 初體驗!怎麼用最新的 laravel 架網站!系列 第 9

[Day 9] 建立資料庫!Laravel 怎麼做資料庫遷移

上幾篇文章內,我們開發了一個讓用戶可以看到名言的功能。

不過,隨著資料量的增長,總不可能將所有要呈現給用戶的資料都寫在程式碼內。

這時候!就是使用資料庫的時候了!

名言需求

我們之前的 inspire 是直接從程式碼內的某個陣列取出名言。現在我們小小修改一下這個需求,讓他可以從資料庫裡面取出。

我們來設計一個簡單的資料表 quotes,來儲存我們的名言:

資料表欄位名稱 資料欄位內容
id 資料 id
content 名言內容
created_at 資料建立時間
updated_at 資料編輯時間

下面我們來聊聊怎麼實作這個資料庫

使用資料庫

在之前我們所使用的 laradock,已經順便幫我們把資料庫建立起來了。不過麻煩的是,因為他所使用的版本太新(latest),所以部分 MySQL 連線工具,如筆者所使用的 Sequel Pro 並不支援。

不過幸運的是,用 laradock 改變資料庫版本是相對容易的事情!我們就來嘗試看看吧!

首先,我們進入 laradock 裡面,找到 .env 檔案。接著在裡面找

MYSQL_VERSION=latest

在這裡把 latest 改成 5.7

接著,因為舊的資料可能會導致錯誤,所以我們要將 laradock 資料庫相關的舊資料清除。

進到 ~/.laradock 這個隱藏資料夾,你會發現裡面有一個 data 資料夾,我們把整個資料夾清空。

最後,我們回到專案的 laradock 資料夾,重新建立 mysql 的服務:

$ docker-compose up -d --build mysql

順利的話,你應該可以看到 Successfully built 之類的字樣。

然後,我們嘗試連線資料庫看看。細心的讀者可能在修改 .env 檔案時就發現了,預設帳號密碼其實寫在裡面:

MYSQL_DATABASE=default
MYSQL_USER=default
MYSQL_PASSWORD=secret

我們用這組帳號密碼,測試連線 127.0.0.1 的 mysql 看看

sequel pro demo

如果能正確連線,看到 default 這個資料庫,就代表我們成功建立起資料庫環境囉!

接著,我們要來介紹一個網頁框架常見的功能:資料庫遷移(migration)

資料庫遷移

什麼是資料庫遷移呢?簡單來說,資料庫遷移很像是針對資料庫格式的版本控制。

過去在開發時,一個很頭痛的事情,就是如何同步各個地方資料庫的格式。如果有新進員工準備要開發,可能要某個工程師匯出自己正在開發的資料庫,或者更糟,直接匯出至正式站的資料庫,讓新的工程師匯入進自己的環境來進行開發。

為了解決這個問題,有的網頁框架引入了一個新的功能:資料庫遷移。利用程式碼來修改資料庫格式,所以資料庫格式和其他程式碼都在版本控制內。如此一來,每次有新的工程師需要建構開發環境時,你就只需要在他取得程式碼的同時,提醒他記得跑一下 migration 就可以了。

解釋起來有點繁瑣,不如我們實作看看吧!

首先,我們修改專案內的 .env,讓專案可以透過前面所說的帳密與資料庫連線:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=default
DB_USERNAME=default
DB_PASSWORD=secret

接著,我們在專案內跑

$ php artisan migrate
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (0.07 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (0.08 seconds)

如果看到這兩個 migration 成功運行,恭喜你,那就代表我們的遷移運作成功囉!我們進資料庫看看:

migration example

可以看到,Laravel 的 migration 建立了三張資料表:一張用來儲存 migration 的內容,另外兩張則是 Laravel 預設的資料表。

撰寫自定義遷移

安裝成功之後,我們來看看如何建立自己的 migration,來改變現有的資料庫格式。

我們先用 artisan 來產生一個 migration create_quotes_table

$  php artisan make:migration create_quotes_table 
Created Migration: 2019_09_10_183501_create_quotes_table

這樣就建立好了,我們來看看裡面寫了些什麼。打開 database/migrations/2019_09_10_183501_create_quotes_table.php

<?php

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

class CreateQuotesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('quotes', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
        });
    }

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

Laravel 很聰明的根據我們命名的 migration 名稱 create_quotes_table 猜到我們可能是要建立 quotes 這個資料表,所以幫我們填寫了部分的內容。

Schema::create('quotes', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->timestamps();
});

這幾行程式的作用是什麼呢?我們直接來測試看看!

我們重新跑一次 php artisan migrate

$ php artisan migrate
Migrating: 2019_09_10_183501_create_quotes_table
Migrated:  2019_09_10_183501_create_quotes_table (0.06 seconds)

然後,我們到資料庫,看看這段程式實際上產生了什麼影響

database quotes schema

成功建立起 quotes 資料表了! 我們看看內容

前面我們所列舉的四個欄位內,有三個都已經預設建立了,真不錯!

我們現在只需要多新增一個欄位 content 就好,首先,我們在資料庫裡面還原我們所做的事情

$ php artisan migrate:rollback --step=1
Rolling back: 2019_09_10_183501_create_quotes_table
Rolled back:  2019_09_10_183501_create_quotes_table (0.03 seconds)

這個指令可以回溯遷移的上一步,根據--step= 裡面的數字改變,回溯多少步驟都可以。

另外補充說明一下 rollback 的機制。在使用 migrate 的時候,會呼叫 up 函式。而使用 migrate:rollback 的時候,我們會呼叫 migration 裡面 down() 這個函式的內容來復原這個 migration 所做的事情。

所以,在每個 migration 裡面,down() 都應該要實作能復原up() 所做的事。

在這裏,我們的 up() 所做的事情是建立 quotes 資料表,所以 down() 所做的事情就是刪除 quotes 資料表,也就是Laravel 所產生的內容:

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

回溯的機制解釋完,還是得看看實際的作用,我們用指定看看是否成功回溯

$ 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_09_10_183501_create_quotes_table          |       |
+------+------------------------------------------------+-------+

成功了!我們確實讓 2019_09_10_183501_create_quotes_table 沒有運作到。

然後我們改寫 2019_09_10_183501_create_quotes_table.php 加入 content

<?php

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

class CreateQuotesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('quotes', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('content', 255);
            $table->timestamps();
        });
    }

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

看出來了嗎?其實我們只加入了一行而已

我們重新跑一次 migrate

php artisan migrate
Migrating: 2019_09_10_183501_create_quotes_table
Migrated:  2019_09_10_183501_create_quotes_table (0.04 seconds)

然後看看資料庫

database quotes schema 3

成功囉!我們建立起需求中的 quotes 資料庫了!


最後總結一下今天我們學到了什麼

今天我們學會 migration 是什麼,怎麼新增 migration,跟怎麼根據需求將 migration 修改成我們要的樣子

希望今天大家有所收穫,我們明天見!


上一篇
[Day 8] 再聊自動測試!怎麼為我們的新網頁加上單元測試
下一篇
[Day 10] 存取資料庫內容!來談 Eloquent Model
系列文
Laravel 6.0 初體驗!怎麼用最新的 laravel 架網站!30

1 則留言

0
ckp6250
iT邦新手 2 級 ‧ 2019-11-27 12:02:04

補充一下,.env 中
MYSQL_USER=
MYSQL_PASSWORD=

不可以有 #
我因密碼中有個 #
以致無法運作。

我要留言

立即登入留言