資料庫課程作業筆記 - 編寫控制器

MARTINPOTTER發表於2019-04-24

控制器

參考文件

這裡涉及比較多的知識,但我們並不用到全部,需要的時候有疑惑可以參考文件,閱讀文件可以幫助我們理解整個流程。

建立資源控制器

php artisan make:controller PurchaseController --resource

php artisan make:controller 後面加 --resource 引數可以建立資源路由,對於我們在 Route 裡面的 resource 所建立的路由,下面我們完成這個路由。
這裡以 購買記錄 舉例,其他控制器擁有類似結構

<?php
namespace App\Http\Controllers;
use App\Http\Requests\PurchaseRequest;
use App\Models\Customer;
use App\Models\Employee;
use App\Models\Product;
use App\Models\Purchase;
use Illuminate\Http\Request;
class PurchaseController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $relations = [
            'customer:'.Customer::ID.','.Customer::NAME,
            'employee:'.Employee::ID.','.Employee::NAME,
            'product:'.Product::ID.','.Product::NAME
        ];
        $data = Purchase::with($relations)->get();
        foreach ($data as $purchase) {
            $purchase[Purchase::CID] = $purchase['customer'][Customer::NAME];
            $purchase[Purchase::EID] = $purchase['employee'][Employee::NAME];
            $purchase[Purchase::PID] = $purchase['product'][Product::NAME];
            unset($purchase['customer']);
            unset($purchase['employee']);
            unset($purchase['product']);
        }
        return view('homework2._list',[
            'title'=>'購買記錄 purchase',
            'columns' => [
                Purchase::CID => '客戶',
                Purchase::EID => '員工',
                Purchase::PID => '產品',
                Purchase::QTY => '數量',
                Purchase::PTIME => '購買時間',
                Purchase::TOTAL_PRICE => '總價',
                Purchase::CREATED_AT => '建立時間',
                Purchase::UPDATED_AT => '修改時間',
            ],
            'data' => $data->toArray(),
            'create' => 'purchase.create',
            'edit' => 'purchase.edit',
            'delete' => 'purchase.destroy'
        ]);
    }
    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        $customers = Customer::all([Customer::ID.' as id', Customer::NAME.' as text']);
        $employees = Employee::all([Employee::ID.' as id', Employee::NAME.' as text']);
        $products = Product::all([Product::ID.' as id', Product::NAME.' as text']);
        return view('homework2.edit_purchase',[
            'customers' => $customers,
            'employees' => $employees,
            'products' => $products
        ]);
    }
    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(PurchaseRequest $request)
    {
        $purchase = new Purchase($request->validated());
        $purchase->save();
        return redirect()->to(route('purchase.index'))->with('success', '新增成功');
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit(Purchase $purchase)
    {
        $customers = Customer::all([Customer::ID.' as id', Customer::NAME.' as text']);
        $employees = Employee::all([Employee::ID.' as id', Employee::NAME.' as text']);
        $products = Product::all([Product::ID.' as id', Product::NAME.' as text']);
        $data = $purchase->toArray();
        $data['customers'] = $customers;
        $data['employees'] = $employees;
        $data['products'] = $products;
        return view('homework2.edit_purchase',$data);
    }
    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(PurchaseRequest $request, Purchase $purchase)
    {
        $purchase->update($request->validated());
        return redirect()->back()->with('success', '更新成功');
    }
    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy(Purchase $purchase)
    {
        try {
            $purchase->delete();
        } catch (\Exception $exception) {
            return redirect()->back()->with('danger',$exception->getMessage());
        }
        return redirect()->back()->with('success', '刪除成功');
    }
}

分析解釋 - 列表

先看看購買記錄列表 index 方法

 public function index()
    {
        $relations = [
            'customer:'.Customer::ID.','.Customer::NAME,
            'employee:'.Employee::ID.','.Employee::NAME,
            'product:'.Product::ID.','.Product::NAME
        ];
        $data = Purchase::with($relations)->get();
        foreach ($data as $purchase) {
            $purchase[Purchase::CID] = $purchase['customer'][Customer::NAME];
            $purchase[Purchase::EID] = $purchase['employee'][Employee::NAME];
            $purchase[Purchase::PID] = $purchase['product'][Product::NAME];
            unset($purchase['customer']);
            unset($purchase['employee']);
            unset($purchase['product']);
        }
        return view('homework2._list',[
            'title'=>'購買記錄 purchase',
            'columns' => [
                Purchase::CID => '客戶',
                Purchase::EID => '員工',
                Purchase::PID => '產品',
                Purchase::QTY => '數量',
                Purchase::PTIME => '購買時間',
                Purchase::TOTAL_PRICE => '總價',
                Purchase::CREATED_AT => '建立時間',
                Purchase::UPDATED_AT => '修改時間',
            ],
            'data' => $data->toArray(),
            'create' => 'purchase.create',
            'edit' => 'purchase.edit',
            'delete' => 'purchase.destroy'
        ]);
    }

這裡的 Purchase::with($relations)->get(); 中的 with 表示使用關係,這個關係定義在模型當中,在 Purchase 模型中定義瞭如上三個關係,使用 customer:id,cname這樣的格式可以查出對於外來鍵的customer資料項中的idcname

 foreach ($data as $purchase) {
            $purchase[Purchase::CID] = $purchase['customer'][Customer::NAME];
            $purchase[Purchase::EID] = $purchase['employee'][Employee::NAME];
            $purchase[Purchase::PID] = $purchase['product'][Product::NAME];
            unset($purchase['customer']);
            unset($purchase['employee']);
            unset($purchase['product']);
        }

這裡將原來的外來鍵換成名稱並去掉對應項

return view('homework2._list',[
            'title'=>'購買記錄 purchase',
            'columns' => [
                Purchase::CID => '客戶',
                Purchase::EID => '員工',
                Purchase::PID => '產品',
                Purchase::QTY => '數量',
                Purchase::PTIME => '購買時間',
                Purchase::TOTAL_PRICE => '總價',
                Purchase::CREATED_AT => '建立時間',
                Purchase::UPDATED_AT => '修改時間',
            ],
            'data' => $data->toArray(),
            'create' => 'purchase.create',
            'edit' => 'purchase.edit',
            'delete' => 'purchase.destroy'
        ]);

這裡 view() 返回 resource\views 中的模板檔案, homework2._list 是我們在 homework2 資料夾下寫的 blade 模板檔案,需要傳遞的引數在後面傳遞對應的陣列,這裡傳遞了顯示的名稱,列表名稱,資料,跳轉的路由,這樣就可以完成我們的列表頁面了。

資料庫課程作業筆記 - 編寫表單驗證

分析解釋 - 建立介面和修改介面

建立新的購買記錄 create 方法

public function create()
    {
        $customers = Customer::all([Customer::ID.' as id', Customer::NAME.' as text']);
        $employees = Employee::all([Employee::ID.' as id', Employee::NAME.' as text']);
        $products = Product::all([Product::ID.' as id', Product::NAME.' as text']);
        return view('homework2.edit_purchase',[
            'customers' => $customers,
            'employees' => $employees,
            'products' => $products
        ]);
    }

修改比建立多了一個引數 Purchase $purchase 這個引數也是通過自動依賴注入完成的,由於在路由我們定義了一個 id 引數,這裡 Laravel 通過這個引數可以自動為我們例項化這個模型物件,這裡會自動找出對應的 id 模型,下面呼叫 to->Array() 方法將模型轉成關係陣列傳遞給試圖。

    public function edit(Purchase $purchase)
    {
        $customers = Customer::all([Customer::ID.' as id', Customer::NAME.' as text']);
        $employees = Employee::all([Employee::ID.' as id', Employee::NAME.' as text']);
        $products = Product::all([Product::ID.' as id', Product::NAME.' as text']);
        $data = $purchase->toArray();
        $data['customers'] = $customers;
        $data['employees'] = $employees;
        $data['products'] = $products;
        return view('homework2.edit_purchase',$data);
    }

由於需要完成下拉選單的操作,所以有三個下拉選單則從三個表中選取 IDNAME 作為下拉選單的對應項,這裡用 [Customer::ID.' as id', Customer::NAME.' as text'] 來將對應的列重新命名,這是使用了原生語句的 as 功能,all 方法是靜態方法,可以快速構造出 mysql 查詢語句查詢全部的資料,裡面傳入需要查詢的列作為 select 引數,想學習跟多關於查詢構造器則可以參考相關文件。

下面的 view 與上面用法一樣,由於設定了三個下拉框所以需要傳入三個屬性。

分析解釋 - 建立與更新

建立和前面的傳參不同,建立需要傳入引數,所以需要經過前面的請求表單驗證。

    public function store(PurchaseRequest $request)
    {
        $purchase = new Purchase($request->validated());
        $purchase->save();
        return redirect()->to(route('purchase.index'))->with('success', '新增成功');
    }

這裡傳入引數使用 PurchasesRequest $request 原理是自動依賴注入,可以參考文件服務容器,簡單的說就是在呼叫方法時 Laravel 會自動呼叫設定好的例項化方法去例項化這個物件,在例項化的過程中會呼叫我們設定在 PurchaseRequest 中的 rule 方法校驗。這種自動依賴注入幫我們省去了很多例項化程式碼,使得我們的控制器寫的如此簡潔。

$request->validated() 可以獲取通過驗證的引數例項化模型 Purchase 並使用 save 方法儲存到資料庫,用 redirect()->to(route('purchase.index'))->with('success', '新增成功') 來返回一個重定向回覆到 route('purchase.index') 這個路由,這個 route() 方法幫我們從路由名中獲取 url,這個路由嗎由前面路由那一章節定義的 Route::resource() 自動定義的資源路由名稱,用 with 來帶上 Session 這樣就可以觸發我們訊息模板 _message.blade.php 來顯示新建成功提示。

 public function update(PurchaseRequest $request, Purchase $purchase)
    {
        $purchase->update($request->validated());
        return redirect()->back()->with('success', '更新成功');
    }

更新與建立的唯一區別就是這個模型由引數的 id 來自動注入,之後幾乎一樣。

分析解釋 - 刪除

public function destroy(Purchase $purchase)
    {
        try {
            $purchase->delete();
        } catch (\Exception $exception) {
            return redirect()->back()->with('danger',$exception->getMessage());
        }
        return redirect()->back()->with('success', '刪除成功');
    }

刪除也通過依賴注入,所以依賴注入實在非常方便。這裡本來可以一句話搞定,但 IDE 提示最好 try catch 一下那就寫得規範一點吧。

其他的控制器都有類似的邏輯,只是介面傳參和連表不同,完成了控制器我們的作業要求也就完成咯~

MARTINPOTTER

相關文章