iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

2
Modern Web

Laravel從入門到放棄…………原生PHP (疑?系列 第 47

[Day 46] Laravel實作 - 商品購買與交易記錄(五)

今天是技術文章的最後一篇了, 主要是要檢視會員交易記錄的內容

檢視會員交易記錄

在交易結束後,會需要提供交易記錄頁面,讓使用者可以隨時看自己的消費歷史記錄,在交易記錄控制器的邏輯會像這樣

app/Http/Controllers/TransactionController.php

<?PHP
namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Shop\Entity\Transaction;

class TransactionController extends Controller
{
    //交易記錄頁面
    public function transactionListPage()
    {
        $user_id = session()->get('user_id');

        //每頁資料量
        $row_per_page = 10;
        //撈取商品分頁資料
        $TransactionPaginate = Transaction::where('user_id', $user_id)
            ->OrderBy('created_at', 'desc')
            ->with('Merchandise')
            ->paginate($row_per_page);

        //設定商品圖片網址
        foreach($TransactionPaginate as $Transaction)
        {
            if(!is_null($Transaction->Merchandise->photo))
            {
                //設定商品照片網址
                $Transaction->Merchandise->photo = url($Transaction->Merchandise->photo);
            }
        }

        $binding = [
            'title' => '交易記錄',
            'TransactionPaginate' => $TransactionPaginate,
        ];

        return view('transaction.listUserTransaction', $binding);
    }
}
?>

透過Transaction Eloquent ORM Model,限制商品資料排序方式為最近交易的資料排在前面,使用paginate()方法建立商品分頁資料,並限制每頁資料量為10筆。

//每頁資料量
$row_per_page = 10;
//撈取商品分頁資料
$TransactionPaginate = Transaction::where('user_id', $user_id)
    ->OrderBy('created_at', 'desc')
    ->with('Merchandise')
    ->paginate($row_per_page);

交易記錄與商品關聯

在顯示交易記錄時,我們會需要顯示這個交易到底購買的商品是哪一個,我們需要能夠顯示該商品的名稱及圖片,可以讓使用者很快地知道是哪一個商品,提高使用者的操作體驗,而交易資料表只有記錄該交易的商品編號,沒有商品相關資訊。此時我們可以到交易(Transaction) Eloquent ORM Model檔案中設定宇商品(Merchandise) Eloquent ORM Model的關聯性,讓撈取交易資料時也可以透過關聯取得商品資訊,關聯的設定會像這樣

app/Shop/Entity/Transaction.php

<?PHP
namespace App\Shop\Entity;

use Illuminate\Database\Eloquent\Model;

class Transaction extends Model {
    //資料表名稱
    protected $table = 'transaction';

    public function Merchandise()
    {
        return $this->hasOne('App\Shop\Entity\Merchandise', 'id', 'merchandise_id');
    }

    //主鍵名稱
    protected $promaryKey = 'id';

    //可以大量指定異動的欄位(Mass Assignment)
    protected $fillable = [
        'user_id',
        'merchandise_id',
        'price',
        'buy_count',
        'total_price',
    ];
}
?>

根據資料表關聯性,可以設定$this->hasOne()擁有一筆資料表資料的關聯,設定$this->belongsTo()資料屬於哪個資料表的關聯資料,設定$this->hasMany();有多個資料筆數的關聯,設定$this->belongsToMany();屬於多個資料列的關聯,等等的相關關聯設定,在設定好關聯關係後,可以讓你直接透過Eloquent ORM Model取得這些關聯設定的資料。

在交易(Transactoin) Eloquent ORM Model檔案中設定方法Merchandise()使用$this->hasOne()方法設定與商品(Merchandise) Eloquent ORM Model的關聯,因為目前每筆交易只會有一個商品,所以用$this->hasOne()設定關聯即可,在關聯設定第一個參數是指定關聯到App\ShopEntity\Merchandise類別的資料,第二個參數為在商品(Merchandise) Eloquent ORM Model參考外來鍵的欄位為id,第三個參數為在交易(Transaction) Eloquent ORM Model資料表自己用來對應關聯的欄位為merchandise_id

撈取交易的商品關聯資料

在設定好交易(Transaction) Eloquent ORM Model的關聯性後,在撈取資料時可以使用->with('Merchandise)的方法,順便將關聯的資料也撈取出來,撈取出來的商品資料會存在每個交易物件的Merchandise變數中,像是$Transaction->Merchandise,所以就可以透過這樣存取關聯的商品資料了。

//每頁資料量
$row_per_page = 10;
//撈取商品分頁資料
$TransactionPaginate = Transaction::where('user_id', $user_id)
    ->OrderBy('created_at', 'desc')
    ->with('Merchandise')
    ->paginate($row_per_page);

在正確取得交易分業資料及關聯的商品資料後,判斷每個商品照片(photo)資料是否有資料,如果有的話,則將圖片相對位置轉換成網址位置(http://),讓模板資料能夠正確地呈現圖片資訊。

//設定商品圖片網址
foreach($TransactionPaginate as $Transaction)
{
    if(!is_null($Transaction->Merchandise->photo))
    {
        //設定商品照片網址
        $Transaction->Merchandise->photo = url($Transaction->Merchandise->photo);
    }
}

在這裡可以看到商品的資料是在交易Transaction中的商品Merchandise屬性中,而商品的圖片則一樣在商品的屬性中$Transaction->Merchandise->photo,用這樣的關聯方式,就可以很方便的操作所有的Eloquent ORM Model的關聯資料了。

在撈取完交易資料後,將交易分頁資料設定在$binding變數中,使用transaction.listUserTransaction模板當作資料的顯示,並將$binding變數的資料傳送到模板中做顯示,在交易記錄頁的模板會長的像下面這樣

resources/views/transaction.listUserTransaction.blade.php

<!-- 指定繼承 layout.master 母模板 -->
@extends('layout.master')

<!-- 傳送資料到母模板,並指定變數為title -->
@section('title', $title)

<!-- 傳送資料到母模板,並指定變數為content -->
@section('content')
<div class="container">
    <h1>{{ $title }}</h1>

    <!-- 錯誤訊息模板元件 -->
    @include('components.validationErrorMessage')

    <table class="table table-condensed">
        <tr>
            <th>商品資料</th>
            <th>圖片</th>
            <th>單價</th>
            <th>數量</th>
            <th>總金額</th>
            <th>購買時間</th>
        </tr>
        @foreach($TransactionPaginate as $Transaction)
        <tr>
            <td>
                <a href="/merchandise/{{ $Transaction->Merchandise->id }}">
                    {{ $Transaction->Merchandise->name }}
                </a>
            </td>
            <td>
                <a href="/merchandise/{{ $Transaction->Merchandise->id }}">
                <img class="img_show" src="{{ $Transaction->Merchandise->photo = $Transaction->Merchandise->photo ?? '/assets/images/default-merchandise.jpg' }}"/>
                </a>
            </td>
            <td>{{ $Transaction->price }}</td>
            <td>{{ $Transaction->buy_count }}</td>
            <td>{{ $Transaction->total_price }}</td>
            <td>{{ $Transaction->created_at }}</td>
        </tr>
        @endforeach
    </table>

    {{-- 分頁頁數按鈕 --}}
    {{ $TransactionPaginate->links() }}
</div>
@endsection

在模板中使用@foreach及@endforeach將交易及商品資料依序顯示出來,並在商品名稱(name)商品照片(photo)中設定連結連接到商品單品檢視頁 /merchandise/{{ $Merchandise->id }},讓消費者可以點擊了解商品詳細資訊,在最後一樣使用$TransactionPaginate->links()的方法產生出分頁頁數按鈕HTML

交易記錄畫面
http://localhost:6943/transaction
https://ithelp.ithome.com.tw/upload/images/20191015/20105694WOq85bJq3o.png

修改首頁以達成各頁面之間的轉換

到目前為止,我們進入各個頁面都要手動輸入網址,這樣子太麻煩了,一般網頁也不會這樣做,而是會有地方讓使用者可以點擊切換頁面,所以我們修改一下首頁的內容,讓頁面之間的切換稍微流暢一點。畢竟這只是示範而已,真正要能夠拿出來當成品的,複雜度比這些還要多很多倍,還有很多細節的地方要去注意。

resources/views/home.blade.php

<!-- 指定繼承 layout.master 母模板 -->
@extends('layout.master')

<!-- 傳送資料到母模板,並指定變數為title -->
@section('title', $title)

<!-- 傳送資料到母模板,並指定變數為content -->
@section('content')
<div class="container">
<ul>
    <li>
        <a href="/merchandise">商品清單檢視</a>
    </li>
    @if(session()->has('user_id'))
        <li>
            <a href="/merchandise/create">商品資料新增</a>
        </li>
        <li>
            <a href="/merchandise/manage">商品管理清單檢視</a>
        </li>
        <li>
            <a href="/merchandise">交易記錄</a>
        </li>
    @endif
</ul>
</div>
@endsection

首頁畫面
https://ithelp.ithome.com.tw/upload/images/20191015/201056946RqY89mAhP.png

商品購買與交易記錄總結

在 商品購買與交易記錄 這個篇幅,我們可以知道Laravel提供DB::beginTransaction();及DB::commit()方法,讓我們可以很輕易地控制資料的完整性及一致性,當交易發生時,需要怎麼鎖定或解除鎖定資料表的資料,而在交易發生錯誤例外時,也可以用DB::roolBack();方法恢復交易之前的資料狀態,並解除鎖定。

在交易結束後,會需要提供使用者交易記錄頁面供使用者作查詢,在查詢資料中可以很方便的使用關聯方法$this->hasOne及 ->with('Merchandise')的方法,設定及撈取交易關聯資料。

這樣我們已經完成了整個基本電子商務網站,在Laravel會用到的資料存取方式及流程了,在這樣的流程中讓你知道了路由(Route)的概念,要怎麼控制哪個網址的請求要到哪個控制器(Controllers)處理,也知道控制器(Controllers)是處理一切請求資料的起點,可以用中介層(Middleware)控制每個路由的存取權限,可以在.env環境變數檔案中設定資料庫的設定值後,透過資料庫遷移(Migration)管理設定資料表的版本,當要撈取資料庫資料時,直接透過使用Eloquent ORM Model讓你可以很快速的撈取資料庫的資料,而Eloquent ORM Model也能幫你做好了安全性的處理。在資料撈取完後,可以在模板(Blade)很方便地用模板語言 {{ }}、@foreach、@for、@if的邏輯去處理資料呈現的方式,而模板也可以很方便的用成元件化的方式去管理,讓共用的模板能夠重複的使用。當我們有需要用到跨專案都需要的功能,像是圖片處理功能時,在Laravel社群中總是能夠找到現成可用的套件可以直接安裝使用。

Laravel將這些開發專案的流程及邏輯,用很簡單的方式讓我們可以達到快速開發的效果,並讓程式可以很簡單且乾淨,相信這樣的實務案例,已經可以讓你很快進入Laravel的快速優雅的開發世界吧。


上一篇
[Day 45] Laravel實作 - 商品購買與交易記錄(四)
下一篇
[Day 47] Laravel從入門到放棄…原生PHP-結語
系列文
Laravel從入門到放棄…………原生PHP (疑?48

尚未有邦友留言

立即登入留言