Laravel 7 CRUD 教學

最近突然想自己寫幾個小服務來玩玩,看了一下目前Laravel好像很多人在用,但在網路上找了很久,大多是官方文件與翻譯文件,找不到幾篇繁中的教學,昨天試玩了一下,就自己來寫一篇簡單的入門教學吧~
開發環境網路上有很多的教學,我就預設各位已經完成開發環境的建置,已經能在執行
laravel new project_name
來建立新專案的狀態囉,喔對了,我不是專職的後端工程師,所以這篇教學如果有不正確的觀念之處,還請大家多多指教~@[email protected]/
先來建立個專案吧~
了解一個Framework,就從CRUD開始,CRUD(Create、Read、Update、Delete),我們來做個簡單的小站台,把增刪改查的功能實做一遍
先建立一個專案,名字叫「corona」,在終端機執行以下的命令
laravel new corona
建立完之後,先到專案路徑下將 storage目錄 與 bootstrap/cache目錄權限先改為777
*這個作法不安全,但本篇的重點在CRUD的實作,先讓Laravel起來吧www
cd corona
chmod -R 777 storage/
chmod -R 777 bootstrap/cache/
為了美觀與方便接下來拉使用者介面,我們裝一下Bootstrap,詳細可以看這一篇
composer require laravel/ui
php artisan ui bootstrap
npm install && npm run dev
然後記得設置一下資料庫連線(.env)
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=corona
DB_USERNAME=corona
DB_PASSWORD=+g/HwxCHTECYRVhUQt1fFbsz2JjdN2NKn7mcJcAX7Nc=
完成之後來做一次 migrate,把專案預設的table寫進DB,順便測試資料庫連線是否正常
php artisan migrate
看到這個表示資料庫連線設定OK了
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (0.03 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated: 2019_08_19_000000_create_failed_jobs_table (0.01 seconds)
建立個資料模型(model)與遷移檔(migration file)吧~
Model就想像成是你拿來定義資料會長什麼樣子,以及之後你與資料庫之間做增刪改查命令的執行者
用以下的指令來建立Model吧
php artisan make:model Corona -m
會看到以下的訊息,表示Migration檔案被產生了出來,它的位置在 database/migrations 下
Model created successfully.
Created Migration: 2020_04_03_062921_create_coronas_table
Migration檔案的日期會依照你執行當下的時間自動命名,上面的訊息表示我在2020年4月3日的6點29分21秒下的指令(應該還要再加8小時,因為專案的時區預設用UTC)
另外,在Laravel裡,Model通常用單數命名,而table name則會是複數,例如Model名是Corona,資料表名是coronas
打開這個Migration檔案,會看到它宣告了兩個function,up()與down()
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCoronasTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('coronas', function (Blueprint $table) {
$table->id();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('coronas');
}
}
up()主要是建立資料表用的,而down()是刪除資料表,但仔細看up()在建議資料表那裡只宣告了兩個欄位,id與timestamps,這裡稍微提一下,過去我們在建立資料表的時候,通常會在最後保留兩個欄位,created_at(建立時間)與updated_at(最後更新),在這裡$table->timestamps(); 就是會產生這兩個欄位,而不用開發者另外宣告
所以我們要來在up()裡宣告除了id與created_at及updated_at之外的欄位
public function up()
{
Schema::create('coronas', function (Blueprint $table) {
$table->id();
$table->string('country_name');
$table->string('symptoms');
$table->integer('cases');
$table->timestamps();
});
}
這裡應該看得出來,欄位宣告的方式就是 $table->型態->(‘欄位名稱’);
宣告完之後來做一次 migrate,把Corona table寫進DB
php artisan migrate
正常完成的話會看到以下兩行
Migrating: 2020_04_03_062921_create_coronas_table
Migrated: 2020_04_03_062921_create_coronas_table (0.02 seconds)
這時到資料庫裡看,Corona資料表已經被建立好了,如果發現欄位名稱或資料型態有錯誤,想改的話,只要用 migrate:rollback 就會回到上一次migrate前的狀態
php artisan migrate:rollback
每一次的migrate:rollback都只會回到上一步,當沒有上一步可以rollback時,就會顯示以下的訊息
Nothing to rollback.
到這裡,資料表建立完成,在Laravel裡,Model預設是放在app目錄下,打開 app/Corona.php,會看到以下的內容
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Corona extends Model
{
//
}
我們在Model裡先做一個fillable屬性(可被填寫的欄位)的宣告
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Corona extends Model
{
protected $fillable = ['country_name', 'symptoms', 'cases'];
}
到這裡,Model基本的建立完成了
來建立路由(routes)與控制器(controller)吧~
現在我們需要來建立一個控制器(接下來都稱controller),可以用以下的命名來建立
php artisan make:controller CoronaController --resource
加上 –resource 可以自動生成預設的七個方法,如果不加 –resoure,Controller會長這樣
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class SomeController extends Controller
{
//
}
Laravel的controller都放在app/Http/Controllers目錄底下
打開CoronaController.php,就會看到預設的七個方法,簡單地來說明一下這幾個方法的用途
- Index(這個方法是用來顯示資源列表,像是列出所有的文章、會員等等)
- Create(這個方法是用來顯示新增資源的畫面,像是新增文章、用戶等等)
- Store(這個方法是用來處理寫入資料庫的)
- Show(這個方法是用來顯示)
- Edit(這個方法是用來顯示修改資料介面)
- Update(這個方法是用來更新資料庫內指定的資料)
- Destroy(這個方法是用來刪除資料庫內指定的資料)
我們先在終端機執行以下指令,查看目前網站可以接受的所有路由有哪些
php artisan route:list
這時應該會看到
+--------+----------+----------+------+---------+--------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+----------+----------+------+---------+--------------+
| | GET|HEAD | / | | Closure | web |
| | GET|HEAD | api/user | | Closure | api,auth:api |
+--------+----------+----------+------+---------+--------------+
因為現在 routes/web.php 只有宣告根目錄( / )路由,及專案自帶的API用的api/user
打開位在 routes 的 web.php,增加一個route宣告
<?php
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return view('welcome');
});
Route::resource('coronas', 'CoronaController'); //增加這行,讓request來自網址 coronas 的都交給 CoronaController 處理
這時我們再回到終端機執行以下指令,查看目前網站可以接受的所有路由
php artisan route:list
如果上面增加route有成功的話,會看到目前網站的路由會變成這樣
+--------+-----------+-----------------------+-----------------+-----------------------------------------------+--------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+-----------+-----------------------+-----------------+-----------------------------------------------+--------------+
| | GET|HEAD | / | | Closure | web |
| | GET|HEAD | api/user | | Closure | api,auth:api |
| | GET|HEAD | coronas | coronas.index | App\Http\Controllers\Co[email protected] | web |
| | POST | coronas | coronas.store | App\Http\Controllers\[email protected] | web |
| | GET|HEAD | coronas/create | coronas.create | App\Http\Controllers\[email protected] | web |
| | GET|HEAD | coronas/{corona} | coronas.show | App\Http\Controllers\[email protected] | web |
| | PUT|PATCH | coronas/{corona} | coronas.update | App\Http\Controllers\[email protected] | web |
| | DELETE | coronas/{corona} | coronas.destroy | App\Http\Controllers\[email protected] | web |
| | GET|HEAD | coronas/{corona}/edit | coronas.edit | App\Http\Controllers\[email protected] | web |
+--------+-----------+-----------------------+-----------------+-----------------------------------------------+--------------+
目前為止網站已經準備好可以上表列出的URI接受request了
接下來設置視圖(views)吧~
Laravel用的Blade模版,也支援Layout,關於Layout,你可以這樣想像,每個頁面都有頁首(header)與頁尾(footer),想像一下,如果頁首或頁尾需要修改,每個頁面我們都要更新到也太累了,所以實務上都會把每個頁面都會用到的部份放在Layout裡
OK,我們先在 resources/vies 目錄下,建立一個 layout.blade.php
上面是基本的HTML結構,其中有幾個需要特別說明的地方
記得在建立專案那一part最後面我們有執行過
composer require laravel/ui
php artisan ui bootstrap
npm install && npm run dev
來安裝Bootstrap 4嗎?如果沒執行,可以執行一下,這幾個命令是讓我們能在這個專案裡使用Bootstrap 4,但安裝完了之後,仍需要在頁面中引用,所以我們在Layout裡引用CSS與JS,這樣就可以讓所有頁面都能用到
先看看Layout的<head>…</head>區塊的最尾巴
<link href="{{ asset('css/app.css') }}" rel="stylesheet" type="text/css" />
以及<body>…</body>區塊的最尾巴
<script src="{{ asset('js/app.js') }}" type="text/js"></script>
這兩段就是在引用Bootstrap 4的CSS與JS的部份
OK,再來我們再來建立三個view
- create.blade.php
- edit.blade.php
- index.blade.php
然後先照著將以下的code塞進去
create.blade.php
@extends('layout')
@section('content')
<style>
.uper {
margin-top: 40px;
}
</style>
<div class="card uper">
<div class="card-header">
新增武漢肺炎案例資料
</div>
<div class="card-body">
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div><br />
@endif
<form method="post" action="{{ route('coronas.store') }}">
<div class="form-group">
@csrf
<label for="country_name">國家:</label>
<input type="text" class="form-control" name="country_name"/>
</div>
<div class="form-group">
<label for="symptoms">症狀 :</label>
<textarea rows="5" columns="5" class="form-control" name="symptoms"></textarea>
</div>
<div class="form-group">
<label for="cases">案例數 :</label>
<input type="text" class="form-control" name="cases"/>
</div>
<button type="submit" class="btn btn-primary">新增</button>
</form>
</div>
</div>
@endsection
然後我們先在CoronaController.php裡的 create() 方法中宣告 return view(‘create’)
// CoronaController.php
public function create()
{
return view('create');
}
這時我們就可以存取看看網站的 /coronas/create ,會看到以下的畫面

驗證資料與寫進資料庫
現在,我們要讓CoronaController能夠使用Corona模型來與資料庫溝通,所以打開CoronaController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Corona; //新增這一行,引用Corona模型
然後就可以在 store() 方法中寫入以下的處理
// CoronaController.php
public function store(Request $request)
{
$validatedData = $request->validate([
'country_name' => 'required|max:255',
'symptoms' => 'required',
'cases' => 'required|numeric',
]);
$show = Corona::create($validatedData);
return redirect('/coronas')->with('success', '武漢肺炎案例已成功儲存');
}
現在來看一下,store() 方法做了哪些事情
store()方法宣告了一個從外部傳進來的request參數,類型是用Laravel內建的 Request,透過這個request參數,可以取得表單傳進來的各欄位資料,像是country_name、symptoms、cases這些欄位的值
然後validateData變數,是用request的validate()方法來進行自定的欄位檢查,以上述為例,我們宣告了三個欄位都是必填(required),且country_name的文字長度最大為255個字元,cases只能是數字
如果表單送進來的欄位值不符合上述的條件,則 $request->validate()會回傳錯誤,也會立即顯示在畫面上,如下圖

關於Laravel 的 Validation詳細有支援哪些,可以看一下官方文件,列得很清楚~
更新待續w