Laravel, PHP

Laravel-PHP與GraphQL API試用

GraphQL 是什麼呢? REST、RESTful API 在 API 界誰不認識呢?
為什麼全世界的工程師都要用 GraphQL 取代傳統 API 呢? 這個由 Facebook 推出的東東有什麼優點呢? 簡單說明 GraphQL 並提供 PHP Laravel 結合 GraphQL 的實做範例.


延伸舊文: 麻瓜也看的懂的 什麼是 API? API 是什麼?

index:

前言

目前 Netflix、Airbnb、GitHub、Twitter、Pinrerest、PayPal、IBM 和台灣的 iCHEF 已經使用 GraphQL, 這麼多公司使用, 我們一定也要跟風用一下. 😎

Wiki 說什麼是 GraphQL: https://zh.wikipedia.org/wiki/GraphQL (tl;dr)
也可參考 延伸 / 說明 / 參考 – GraphQL 入門

需求情境

網站分桌面版、行動版, APP 也有 iOS, Android. 細分的話還有一般使用者和管理員用的操作介面.
每個環節、畫面都會用到一樣的資料.
但是畫面上顯示、取用的 資料欄位 可就不一樣了…

iOS APP 需要使用者的寵物資料、Android APP 則要使用者全家人的資料, mobile 網站因為畫面小所以只要使用者姓名, 而桌面版網站因為每個人都是 4k 螢幕所有資料全都要 😂

GraphQL API 我全都要!

天啊!!
後端工程師們要開幾支 API 呢? 前端用、後台用? mobile 網站? APP 專用?
這樣維護、開發、管理這些 API 有多累人.
使用 restful api 的時候可能就會出現…

/user/123
/user/123?platform=ios
/user/123?platform=web&fields=id,name
/user/123?platform=android&family=true
/user/123?platform=web&role=admin
或
/admin/user/123

他們相似但又不盡相同 😱

為這解決這樣的問題, GraphQL 出現了!!
簡單來說~
後端工程師把資料全放在同一個 API. 前端 (mobile 網站、 iOS / Android APP) 工程師想要資料嗎? 想要什麼資料自己拿, 全放在同一個 API 了!!!

GraphQL 有什麼優點?

  • 多平台的時代, 寫一次用多次
    不同平台所需的資料數量、格式都不同, client 端可以透過 GraphQL API 取想要的資料、欄位, 有效減少 request 次數!

  • 前、後端都能暸解 Data Schema
    開發上的配合流程大概就像下圖一樣~
GraphQL API 定義 example
(source by https://www.slideshare.net/nburk/the-graphql-ecosystem-in-2018)
  • 統一接口
    我把資料都放在哪了, 要什麼自己拿

  • 文件產出 / Docs as Code
    GraphQL API 在製作/開發時會引導你把文件完成
    完美達成 “程式就是文件”

  • 關連資料取得
    資料間的連結關係也是 GraphQL 強大的特色之一
    可以從 user > post > like > user > post 將資料一路連結取出
    e.g. 查出 使用者 某篇 文章 所含的 Like, 然後這些 Like 使用者文章 資料
graphql!
(source by https://blog.apollographql.com/explaining-graphql-connections-c48b7c3d6976)
  • 強型別 – 統一型態
    不用再擔心每支 API 各種情況不同的回傳型態, empty string, null, nil, 0 ?
    graphql basic type: StringIntFloatBoolean, and ID
    當然也能自訂 type 例如 PhoneNumber, Email 等…

  • multiple queries in one request
    在特殊情況下, GraphQL 可以合併 query 送出, 不用像 rest api 一樣取使用者資料發一個 request, 取使用者文章資料再發一個 reqeust…

GraphQL 的缺點

  • 開發難度增度
    功能愈多, 難度愈高; 目前沒有一個推薦的 best practice…

  • 學習成本 / Fits Into Your Product
    新、潮的技術很有趣也或許很有產生, 但除了學會它之外,
    安全的置入現行產品內才是真正的挑戰. 要如何安排手上現有產品 rest api 和 graphql api 並存或取代就是個大學問了.

  • 注意不要變成 RESTful API 

  • Cache 實作問題
    開放隨便取資料, 讓資料難以建立 cache…
    但可以從策略面處理.

  • 優點即缺點的 n+1 Query 問題
    graphql 的關連資料取得, 但很容易造成 db 重覆(迴圈) query 的問題
    這也是最難處理的問題之一

Laravel-PHP與GraphQL API試用與實作

GraphQL 和 Laravel 要怎麼結合呢?
透過一個實驗性的 Project 來測試.
這是一個蒐集實體活動電商(手作蛋糕, 手作金飾等…), 再透過 graphql api 將資料顯示出來

🐙GitHub repo: cscolabear/rainy-to-do-app-api
(詳細說明於 GITHUB readme.md)

repo 內有兩個 branch: master 和 nuwave/lighthouse
分別使用了兩種 Laravel GraphQL 套件測試~

branch: masterrebing/graphql-laravel, Laravel 上比較老牌的 graphql 套件
branch: nuwave/lighthouse 則是未來發展看好

兩個套件各有優點~
我這邊則是使用 rebing 當做主要範例~


初期使用 playground, 方便 client / server 端做觀察、測試

graphql-playground 實際操作
介面上也保含 DOCS 和 Schema 說明

一般來說 GraphQL 都是使用 POST 發出 request ~
不過為了測試方便, 目前讓 get 也能正常取得資料, 下為取得 5 筆手作行程, 指定回傳欄位為: id, 價格(price), 行程來源(source name), 分類名稱(category name) 然後 price 由高至低排序

request (get):

https://workxplay.net/rtd-app/graphql?query=query%20{products(count:5%20orderBy:{field:%22price%22%20order:DESC}){data{id%20title%20price%20source{name}%20category{name}}total%20per_page%20last_page}}

response:

{"data":{"products":{"data":[{"id":238,"title":"Hananeco \u82b1\u8c93\u86cb\u7cd5 - \u97d3\u5f0f\u64e0\u82b1 \u2027 \u9910\u684c\u4e0a\u7684\u82b1\u6d77\u7cfb\u5217","price":3000,"source":{"name":"niceday"},"category":{"name":"\u73a9\u6a02\u5eda\u623f"}},{"id":237,"title":"Miss J Baking Studio - \u4f3c\u82b1\u93e1\u9762\u86cb\u7cd5","price":3000,"source":{"name":"niceday"},"category":{"name":"\u73a9\u6a02\u5eda\u623f"}},{"id":24,"title":"\u3010\u65b0\u5317\u798f\u9686\u3011\u73a9\u7ffb\u4eca\u590f\uff01\u514d\u88dd\u5099\u9732\u71df + SUP","price":3000,"source":{"name":"niceday"},"category":{"name":"\u611b\u4e0a\u6236\u5916"}},{"id":163,"title":"\u7368\u4e00\u7121\u4e8c\u91d1\u5de5\u9ad4\u9a57\uff01\u89aa\u624b\u6253\u9020\u9ad8\u8cea\u611f\u6212\u6307","price":2980,"source":{"name":"niceday"},"category":{"name":"\u85dd\u6587\u624b\u4f5c"}},{"id":162,"title":"\u9ad4\u9a57\u50b3\u7d71\u91d1\u5de5\u7684\u624b\u4f5c\u6eab\u5ea6 - \u6572\u4e00\u53ea\u9ad8\u8cea\u611f\u624b\u74b0","price":2980,"source":{"name":"niceday"},"category":{"name":"\u85dd\u6587\u624b\u4f5c"}}],"total":248,"per_page":5,"last_page":50}}}

簡單的順序為~
– 安裝 rebing/graphql-laravel 套件, 並記得 vendor:publish
– 建立 GraphQL/Query – 核心 query resolve 的部份, 定義 query argument
– 建立 GraphQL/Type – 定義欄位 type
– config/graphql.php – 開放 schema query 入口, 定義欄位 type 對應到的 GraphQL/Type

承上! 最好先暸解 graphql 內 schema, type 至 query 間的關係
ref. https://graphql.org/learn/schema/

總結/結論

最初透過 restful 和 GraphQL API 並行的方式將 GraphQL 帶入~
可以先從小功能、新功能開始帶入
並不需要把 restful api 廢除
重要的是挑選適合、舒服的方法

延伸 / 說明 / 參考

發表迴響