iT邦幫忙

2022 iThome 鐵人賽

DAY 22
0
自我挑戰組

laravel+vue 學習系列 第 22

Day22. 前台 API 與頁面之一 (建立 API 資源)

  • 分享至 

  • xImage
  •  

一、建立 API controller

  1. artisan 指定建立
    • 前台規劃透過 pj_relationship_category 取得資料, 資料表內紀錄該筆資料屬於哪一個全站分類, 由哪一個模組提供的內容
    // --api 生成基本 function
    php artisan make:controller FrontController --api
  1. 設定路由
    // routes/api.php
    // 設定 group 以 name front 開頭, 路徑前綴 front
    Route::name('front.')->prefix('front')->group(function(){   

        // 顯示單一筆資料
        Route::get('/{front}', 
                    [\App\Http\Controllers\Api\FrontController::class, 
                    'show'])
                    ->name('show');

        // 顯示單一類別列表
        Route::get('/category/{category}', 
                    [\App\Http\Controllers\Api\FrontController::class, 
                    'category'])
                    ->name('category');
    });

https://ithelp.ithome.com.tw/upload/images/20220927/20128127FUjRJR4eW8.png

二、建立 Resource 統一回傳格式

  1. 建立 Trait 給 Models, 按照規則設定要顯示於前台內容
  • 建立 Trait
    namespace App\Traits;

    /**
     * 設定 model id, 提供給共用圖片資料分辨屬於哪一個 model 下的資料
     */
    trait HasFrontData {        

        /**
         * 回傳前台統一格式
         * 
         * category: 網站總分類
         * title: 資料標題
         * sub_title: 資料副標題
         * create: 建立時間
         * update: 建立時間
         * create_person: 建立人員
         * update_person: 修改人員
         * content: 主內容
         * simple_content: 簡介內容
         * other: 其他內容 e.g. 商品的規格、分類等, 由頁面本身判斷顯示
         */
        public function get_front_data() {
            // 預設回傳
            return $this->toArray();
        }

    }
  • 要顯示於前台的 Models 設定回傳內容
    class Product extends Model
    {
        use HasFrontData;
        
        // ...其他程式省略
        
        /**
         * 回傳前台統一格式
         * 
         * category: 網站總分類
         * title: 資料標題
         * sub_title: 資料副標題
         * create: 建立時間
         * update: 建立時間
         * create_person: 建立人員
         * update_person: 修改人員
         * content: 主內容
         * simple_content: 簡介內容
         * other: 其他內容 e.g. 商品的規格、分類等, 由頁面本身判斷顯示
        */
        public function get_front_data() {

            return [
                'category' => strip_tags($this->category->name),
                'title' => strip_tags($this->name),
                'sub_title' => null,
                'create' => date("Y-m-d", strtotime($this->created_at)),
                'update' =>  date("Y-m-d", strtotime($this->updated_at)),
                'create_person' => null,
                'update_person' => null,
                'content' => $this->intro,
                'simple_content' => strip_tags($this->simple_intro),
                'other' => [
                    'images' => $this->images,
                    'specs' => $this->specs
                ]
            ];

        }
    }
  1. 建立 Resource 回傳單一筆資料
  • artisan 指令建立 Resource
    php artisan make:resource FrontResource
  • FrontResource 內會傳入 Eloquent, 因為有使用 Trait 所以可以呼叫 get_front_data() 方法回傳統一格式
    // FrontResource 可以修改 toArray() 方法設定回傳格式
    public function toArray($request)
    {
        return $this->get_front_data();
    }
  • Controller 取得資料回傳
    // App\Http\Controller\Api\FrontController
    // 路由會傳入資料 pj_relationship_category id
    public function show($id)
    {
        // 模組與資料的關係表
        $relation = app(\App\Models\RelationShipCatory::class);
        $r_object = $relation->findOrFail($id);

        // 在關係表中查到該筆資料屬於哪一個模組
        $datetype = app(\App\Models\DataType::class);
        $d_object = $datetype->findOrFail($r_object->data_id);
        
        // 得到模組後, 建立 eloquent
        $m_object = new $d_object->class_name;
        $data = $m_object->findOrFail($r_object->item_id);
        
        // Resource 內會呼叫 get_front_data() 取回統一的格式
        return new FrontResource($data);
    }
  • 使用 Postman 測試回傳結果
    https://ithelp.ithome.com.tw/upload/images/20220927/20128127LxfY1G2tmD.png

三、建立 Resource Collection

  1. 依全站類別區分, 路由會接受到分類的 id
    // App\Http\Controller\Api\FrontController
    
    public function category($id){

        // 模組與資料的關係表
        $relation = app(\App\Models\RelationShipCatory::class);
        $r_object = $relation->where('category_id', $id)->paginate($this->page_count);
        
        // 模組
        $subset = $r_object->groupBy('data_id');
        
        $datetype = app(\App\Models\DataType::class);
        foreach($subset as $model_id => $items ) {            
            
            $d_object = $datetype->findOrFail($model_id);

            // 建立 eloquent
            $m_object = new $d_object->class_name;
            // 取出所有資料 id
            $datas_id = array_column($items->toArray(), 'item_id');
            $datas = $m_object->whereIn('id', $datas_id)->get(); 
            // 將 key 改為資料的 id   
            $datas = $datas->keyBy('id');
            
            // 依序回填到 $r_object 物件內
            foreach ( $items as $key => $item ) {  
                // 利用 Resource 統一回傳內容
                $item->front = new FrontResource($datas[$item->item_id]);
            }

        }
        
        return response()->json($r_object);
    }
  • 使用 Postman 測試回傳結果
    https://ithelp.ithome.com.tw/upload/images/20220927/201281271Y4aAqQL3P.png

github 進版
剩下的明天繼續


上一篇
Day21. RESTful API
下一篇
Day23. 前台 API 與頁面之二 (前台 Vue 環境)
系列文
laravel+vue 學習32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言