# Using Database in Laravel
###### tags: `MCL` `web`
References
~ * https://laravel.com/docs/5.8/migrations
* https://laravel.com/docs/5.8/seeding
* https://laravel.com/docs/5.8/eloquent
這篇的範例情境是值班打卡紀錄 `check_records`。
## Laravel 上的遷移表
基本上建立遷移表有三種方式:
1. 自己加檔案
2. 直接透過指令建立遷移表
3. :crown: 建立 ORM 的同時順便建立遷移表
### 建立 ORM 的同時順便建立遷移表
ORM (物件關聯對映, Object Relational Mapping) 的功能是實現程式語言當中與各種類型資料的互動。
在 Laravel 建立 ORM 的指令如下:
```php
php artisan make:model [駝峰式資料表名稱 (單數)] -m
```
```php
php artisan make:model CheckRecord -m
```
後面 `-m` 的意思就是建立 ORM 的同時也會建立對應的遷移表。
而這樣的動作會產生兩個檔案:
- 物件檔案:`app/CheckRecord.php`
- 遷移檔案:`database/migrations/xxxx_xx_xx_xxxxxx_create_check_records_table.php`
### [Optional] 直接透過指令建立遷移表
複習一下,上周我們使用 `migrate` 指令遷移預設遷移表到資料庫系統去。這次我們會練習建立自己的遷移表,並且使用同樣的方式建立自己的資料表。
建立遷移表的指令如下:
```bash
php artisan make:migration create_[蛇底式資料表名稱 (複數)]_table
```
此時他就會在 `database/migrations` 下建立一個對應於資料表名稱的遷移表。
> 1. 資料表名稱通常為**複數**
> 2. 如果是多名詞想要區隔的話,會使用底線 `_` (snake_case naming style)
根據這次的範例情境,我們的指令如下:
```bash
php artisan make:migration create_check_records_table
```
### 編輯遷移表
此時你會在 `database/migrations` 中看到對應的 `.php` 檔。他的內容會長得像下面這個樣子:
```php=
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCheckRecordsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('check_records', function (Blueprint $table) {
$table->bigIncrements('id'); // 相當於 index 的東西
/**
* 這邊可以加你想要增加的欄位
*/
$table->timestamps(); // 時戳 (建立時間、更新時間)
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('check_records');
}
}
```
思考一下我們需要的欄位以及他對應的型態:
| 欄位名稱 | 型態 | 備註 |
| ---------- | --------------- | --------------------------------------------------- |
| id | bigIncrements | 系統會自動記數 (視為這筆資料的唯一識別碼,很重要!!) |
| user_id | unsignedInteger | 對應使用者 index |
| check_time | dateTime | 這個有到秒哦 |
| comment | string | 如果想儲存換行要使用 `text` |
> 更多欄位型態可以查 Laravel 官方列舉的清單:
> https://laravel.com/docs/5.8/migrations#columns
接著把這個型態轉換成程式碼,放到剛剛生成的遷移表:
```php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCheckRecordsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('check_records', function (Blueprint $table) {
$table->bigIncrements('id'); // 相當於 index 的東西
$table->unsignedInteger('user_id');
$table->dateTime('check_time');
$table->string('comment');
$table->timestamps(); // 時戳 (建立時間、更新時間)
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('check_records');
}
}
```
放好之後我們就可以嘗試遷移到 SQL Server 了,同樣的指令:
```bash
php artisan migrate
```
遷移指令成功的話,你就可以看到你寫的資料表就出現在資料庫上面了。
### 透過 `seeder` 建立種子資料 (或者說是假資料)
你可能會需要事先在資料表中先填入一些資料,通常這件事情有這幾種發生可能:
1. 有些功能需要在有資料的前提下才能運作,不然會報錯
2. 基於開發需求,預先寫好一些測試資料方便使用
同樣也可以透過 `artisan` 建立 `seeder` :
```bash
php artisan make:seeder CheckRecordsTableSeeder
```
建立好後他 `database/seeds/CheckRecordsTableSeeder.php` 會是一個沒有實際程式碼的檔案,這時候我們可以加上個人指令去新增資料列:
```php
<?php
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB; // 記得要加
class CheckRecordsTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
DB::table('check_records')->insert([
'user_id' => 1,
'check_time' => '2020-05-07 21:00',
'comment' => '安安',
'created_at' => '2020-05-07 21:00',
'updated_at' => '2020-05-07 21:00'
]);
}
}
```
完成之後換到同目錄下的 `DatabaseSeeder.php`,將目前的 seeder class 加進去:
```php
<?php
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* @return void
*/
public function run()
{
$this->call([
CheckRecordsTableSeeder::class
]);
}
}
```
#### 執行
```bash
php artisan db:seed
```
### 常用的 `migrate` 指令
- 清空資料庫 `php artisan migrate:reset`
- 刷新資料庫 `php artisan migrate:refresh` (相當於清空 + 遷移)
- 遷移時附帶種子資料 `php artisan migrate --seed`
## 使用 ORM
在 controller 前面加上 `use App\CheckRecord;`,即可對此資料表進行操作,以下是實現查詢功能的範例:
* `routes/web.php`
```php
<?php
Route::group(['middleware' => 'auth'], function () {
Route::get('/check', 'DateController@getCheckRecords');
Route::get('/add', 'DateController@addCheckRecord');
});
```
* `app/Http/Controllers/DateController.php`
```php
<?php
namespace App\Http\Controllers;
use Auth;
use App\CheckRecord;
use Illuminate\Http\Request;
class DateController extends Controller
{
public function getCheckRecords(Request $request)
{
$data = CheckRecord::whereUserId(Auth::user()->id)->get();
return $data;
}
public function addCheckRecord(Request $request)
{
$checkRecord = new CheckRecord;
$checkRecord->user_id = Auth::user()->id;
$checkRecord->check_time = now();
$checkRecord->comment = $request->get('comment');
$checkRecord->save();
return redirect('/check');
}
}
```