【筆記-Laravel】Laravel 7 CRUD 範例

資料來源:Laravel 7 CRUD Example | Laravel 7 Tutorial Step By Step

說明:

這是PHP Laravel的一個CRUD範例,示範如何一步一步建立一個CRUD的應用。

PHP Laravel是一個後端系統框架,可以讓一個程式設計師專注於應用程式問題邏輯(解決商用/工業問題),不用花太多心思在技術細節上,也就是說,一個資訊系的學生只需要建立技術觀念,在不需要實作技術細節的狀況下,就能建立一個面面俱到的應用程式。一般來說,一個資訊系的學生要要能力寫一個應用系統往往要學非常多的學科、技術、觀念等,才有辦法建立一個”完整”的應用程式,難度之高,連我都覺得寫系統是一個超級有挑戰的工作,底下這張圖非常傳神,”嚇死一堆寶寶了”,不少念了四年的資訊系學生不想碰程式設計(特別是女生,大部份是因為社會刻板印象吧,自覺女生本來應該很”不理工”。)。因為要寫一個好的系統不容易,導入適當的框架到學生的學習是有必要的,不要coding底層細節來建立一個完整的系統,只是要學Laravel框架,基礎也是要有的,JavaScript、HTML、CSS、PHP、Bootstrap(前端UI)、SQL、資料庫模型、系統分析與設計…,有好的基礎才能在框架協助下建立好的應用程式(框架不是銀子彈)。

圖片來源 https://aprogrammerlife.com/most-viewed/computer-science-students-1010?fbclid=IwAR1zeYTa61eJSeOA76JVvz6riE9-7ZohZFlVcm3UFt9lXkWbCI0n_Ms0_hg

 

新增專案:

  • laravel new crud-example

或者使用下列的指令:

  • composer create-project –prefer-dist laravel/laravel crud-example

執行完畢會新增一個目錄crud-example,進入該目錄,並且更新前端的相依資料

  • cd crud-example
  • npm install 

編輯.env檔,修改資料庫連接資料:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=wellsche_crud_example
DB_USERNAME=wellsche_laravel
DB_PASSWORD=xxxxxxxx

首先編輯/app/Providers/AppServiceProvider.php,加入表料庫schema相關的修改:

<?php

namespace App\Providers;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
      Schema::defaultStringLength(191);
    }
}

執行:

  • php artisan migrate

所需要的資料表格schema會建立好

建立model與mirgation檔

  • php artisan make:model Corona -m

上面指令會產生2個檔案:

  1. app目錄:Corona.php
  2. database/migrations目錄:[timestamp]create_coronas_table.php

編輯[timestamp]create_coronas_table.php

原來的create_coronas_table.php裏的up函式:

public function up()
{
    Schema::create('coronas', function (Blueprint $table) {
        $table->id();
        $table->timestamps();
    });
}

 

改為:(加入2個字串表格欄位:country_name與symptoms,1個整數表格欄位cases)

public function up()
{
        Schema::create('coronas', function (Blueprint $table) {
            $table->id();
            $table->string('country_name');
            $table->string('symptoms');
            $table->integer('cases');
            $table->timestamps();
        });
 }

上面定義了corons資料表格的欄位schema,定義完後再下一次指令,完成資料表格的schema設定:

  • php artisan migrate

此時可到資料庫那邊檢視coronas這個表格的欄位建立情形。

如果要反轉migration的過程,可以執行php artisan migrate:rollback來刪除coronas這個表格 (會執行down()函式)。

接著編輯Corona.php,來加入fillable的屬性:(設置’country_name’, ‘symptoms’, ‘cases’這三個欄位是可以填寫的。)

<?php

// Corona.php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Corona extends Model
{
    protected $fillable = ['country_name', 'symptoms', 'cases'];
}

Step 3. 建立路由與控制器

  • php artisan make:controller CoronaController –resource

會在CoronaController.php(app\Http\Controllers)建立6個方法:

  1. index 顯示Coronas資料清單
  2. Create 顯示Coronas的新增表單
  3. Store 將Create那邊的表單所傳來的資料儲存至資料庫。
  4. Show  顯示一個特定的Coronas資料
  5. Edit 顯示Coronas資料的修改表單
  6. Update 將Edit那邊的資料新增至資料庫
  7. Destroy 刪除一筆Corona

CoronaController.php列表:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class CoronaController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }
}

 

編輯routes\web.php,插入以下程式碼:

// web.php

Route::get('/', function () {
    return view('welcome');
});
Route::resource('coronas', 'CoronaController');

透過–resource, 你可以使用這個方法resource()產生以上所有的路由,而不需要一一個別地指定以上的路由。

Actually, by adding the following code line, we have registered the multiple routes for our app. We can check it using the following command.

實際上,藉由加入該程式碼,我們已經為我們的應用註冊了多個路由,我們可使用底下的命令來檢視這些路由:

php artisan route:list

輸出:

 

Step 4: Configure Bootstrap 4

安裝Bootstrap和Vue套件:

  • composer require laravel/ui

安裝bootstrap ui鷹架:

  • php artisan ui bootstrap

編譯初生的鷹架:

  • npm install && npm run dev

Step 5: Create the views

建立並編輯views目錄下的layout.blade.php,加入下列的code:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Laravel 7 CRUD Example</title>
  <link href="{{ asset('css/app.css') }}" rel="stylesheet" type="text/css" />
</head>
<body>
  <div class="container">
    @yield('content')
  </div>
  <script src="{{ asset('js/app.js') }}" type="text/js"></script>
</body>
</html>

一樣,在views目錄建立三個檔案:

  1. create.blade.php
  2. edit.blade.php
  3. index.blade.php

在create.blade.php加入:

@extends('layout')

@section('content')
<style>
  .uper {
    margin-top: 40px;
  }
</style>
<div class="card uper">
  <div class="card-header">
    Add Corona Virus Data
  </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">Country Name:</label>
              <input type="text" class="form-control" name="country_name"/>
          </div>
          <div class="form-group">
              <label for="symptoms">Symptoms :</label>
              <textarea rows="5" columns="5" class="form-control" name="symptoms"></textarea>
          </div>
          <div class="form-group">
              <label for="cases">Cases :</label>
              <input type="text" class="form-control" name="cases"/>
          </div>
          <button type="submit" class="btn btn-primary">Add Data</button>
      </form>
  </div>
</div>
@endsection

編輯CoronaController.php,在create方法下加入

// CoronaController.php

public function create()
{
   return view('create');
}

此時,到http://fgchen.com:8000/coronas/create,會看到底下的畫面:

 

Step 6: Add Validation rules and save data

在這個步驟,我們要加上Laravel form Validation

編輯CoronalController.php,加入app\Corona的名稱空間的使用:

<?php

// CoronaController.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Corona;

並且在CoronalController.php的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', 'Corona Case is successfully saved');
}

 

store()方法接收到從建立表單來的$request資料物件,我們使用$request->validate這個方法定義資料的確認規則,使用關聯陣列分別對不同欄位給定確認規則,每一個欄位的確認規則以”|”指定多的規則。

加入的規則在確保當使用者沒有給資料(required)、最大255個字元、數值的規則下,驗證失效,畫面會有適當的紅色提示字眼:

 

Step 7: Display the data

我們接著編輯CoronaController的index功能:

// CoronaController.php

public function index()
{
        $coronacases = Corona::all();

        return view('index', compact('coronacases'));
}

 

建立views目錄下的index.blade.php

@extends('layout')

@section('content')
<style>
  .uper {
    margin-top: 40px;
  }
</style>
<div class="uper">
  @if(session()->get('success'))
    <div class="alert alert-success">
      {{ session()->get('success') }}  
    </div><br />
  @endif
  <table class="table table-striped">
    <thead>
        <tr>
          <td>ID</td>
          <td>Country Name</td>
          <td>Symptoms</td>
          <td>Cases</td>
          <td colspan="2">Action</td>
        </tr>
    </thead>
    <tbody>
        @foreach($coronacases as $case)
        <tr>
            <td>{{$case->id}}</td>
            <td>{{$case->country_name}}</td>
            <td>{{$case->symptoms}}</td>
            <td>{{$case->cases}}</td>
            <td><a href="{{ route('coronas.edit', $case->id)}}" class="btn btn-primary">Edit</a></td>
            <td>
                <form action="{{ route('coronas.destroy', $case->id)}}" method="post">
                  @csrf
                  @method('DELETE')
                  <button class="btn btn-danger" type="submit">Delete</button>
                </form>
            </td>
        </tr>
        @endforeach
    </tbody>
  </table>
<div>
@endsection

結果畫面:

Step 8: Create Edit and Update Operation

我們接著編輯CoronaController的edit功能:

// CoronaController.php

public function edit($id)
{
        $coronacase = Corona::findOrFail($id);

        return view('edit', compact('coronacase'));
}

建立與編輯edit.blade.php

@extends('layout')

@section('content')
<style>
  .uper {
    margin-top: 40px;
  }
</style>
<div class="card uper">
  <div class="card-header">
    Edit Corona Virus Data
  </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.update', $coronacase->id ) }}">
          <div class="form-group">
              @csrf
              @method('PATCH')
              <label for="country_name">Country Name:</label>
              <input type="text" class="form-control" name="country_name" value="{{ $coronacase->country_name }}"/>
          </div>
          <div class="form-group">
              <label for="symptoms">Symptoms :</label>
              <textarea rows="5" columns="5" class="form-control" name="symptoms">{{ $coronacase->symptoms }}</textarea>
          </div>
          <div class="form-group">
              <label for="cases">Cases :</label>
              <input type="text" class="form-control" name="cases" value="{{ $coronacase->cases }}"/>
          </div>
          <button type="submit" class="btn btn-primary">Update Data</button>
      </form>
  </div>
</div>
@endsection

編輯CoronaController的update功能:

// CoronaController.php

public function update(Request $request, $id)
{
        $validatedData = $request->validate([
            'country_name' => 'required|max:255',
            'symptoms' => 'required',
            'cases' => 'required|numeric',
        ]);
        Corona::whereId($id)->update($validatedData);

        return redirect('/coronas')->with('success', 'Corona Case Data is successfully updated');
}

Step 9: Create Delete Functionality

編輯CoronaController destroy 方法:

// CoronaController.php

public function destroy($id)
{
        $coronacase = Corona::findOrFail($id);
        $coronacase->delete();

        return redirect('/coronas')->with('success', 'Corona Case Data is successfully deleted');
}

整個CoronaController.php列表:

<?php

// CoronaController.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Corona;

class CoronaController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $coronacases = Corona::all();

        return view('index', compact('coronacases'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        return view('create');
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    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', 'Corona Case is successfully saved');
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        $coronacase = Corona::findOrFail($id);

        return view('edit', compact('coronacase'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        $validatedData = $request->validate([
            'country_name' => 'required|max:255',
            'symptoms' => 'required',
            'cases' => 'required|numeric',
        ]);
        Corona::whereId($id)->update($validatedData);

        return redirect('/coronas')->with('success', 'Corona Case Data is successfully updated');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        $coronacase = Corona::findOrFail($id);
        $coronacase->delete();

        return redirect('/coronas')->with('success', 'Corona Case Data is successfully deleted');
    }
}

最後,我自己在首頁index.blade.php加上一個”Add a new coron virus record”按鈕:

@extends('layout')

@section('content')
<style>
  .uper {
    margin-top: 40px;
  }
</style>
<div class="uper">
  @if(session()->get('success'))
    <div class="alert alert-success">
      {{ session()->get('success') }}
    </div><br />
  @endif
  <h1 class="dislay-1">Corona virus records in the wrold</h1>
  <a class="btn btn-primary" href="{{ route('coronas.create') }}" role="button" style="margin-bottom:10px">Add</a>
  <table class="table table-striped">
    <thead>
        <tr>
          <td>ID</td>
          <td>Country Name</td>
          <td>Symptoms</td>
          <td>Cases</td>
          <td colspan="2">Action</td>
        </tr>
    </thead>
    <tbody>
        @foreach($coronacases as $case)
        <tr>
            <td>{{$case->id}}</td>
            <td>{{$case->country_name}}</td>
            <td>{{$case->symptoms}}</td>
            <td>{{$case->cases}}</td>
            <td><a href="{{ route('coronas.edit', $case->id)}}" class="btn btn-primary">Edit</a></td>
            <td>
                <form action="{{ route('coronas.destroy', $case->id)}}" method="post">
                  @csrf
                  @method('DELETE')
                  <button class="btn btn-danger" type="submit">Delete</button>
                </form>
            </td>
        </tr>
        @endforeach
    </tbody>
  </table>
<div>
@endsection

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料