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 螢幕所有資料全都要 😂

天啊!!
後端工程師們要開幾支 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
    開發上的配合流程大概就像下圖一樣~
(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 使用者文章 資料
(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 廢除
重要的是挑選適合、舒服的方法

延伸 / 說明 / 參考

可樂

Recent Posts

plain PHP 搭配 Slack 進行錯誤追蹤、回報(Error Tracking、Error Handling)

錯誤追蹤、回報非常重要,看到的錯誤才知道怎麼修。現今 PHP 流行的 Laravel 有很好的 Error Tracking, Error Handling。但 plain PHP 怎麼辦呢? 在 production 為了安全考量會設定…

4 years ago

Drone CI/CD 配合 Github 使用 Rsync 進行 Deploy

jenkins、circleci、travis 或 Gitlab CI 皆為目前暫知名的 CI/CD 服務,各自缺點也不言而喻...過於肥大、收費略高(?)、速度不夠快執問題...此時使用 go language 開發的 Drone 就出現啦,完全 docker 容器化的運行方式讓整個 CI…

4 years ago

Nginx brotli 設定

網頁壓縮技術中 gzip 很好用,deflate 己經過時,但你聽過 brotli 嗎? 有著比 gzip 更好、更快的壓縮效率。看起來利大於弊有什麼不用他的理由嗎?簡單從優、缺點來看 brotli!到底 brotli 布羅特利是什麼、如何設定呢。 目前大多的 web server…

4 years ago

本機使用 Docker 容器內 PHP (wrapper/expose PHP)

為什麼要讓本機使用 Docker 內 PHP? 情境... docker 容器內用的是 PHP 7.4 但你的開發本機還在跑 PHP 5.6 或是更舊,因為 dockerize 的關係會將所有相關環境都轉移到…

4 years ago

為什麼你需要密碼管理工具

為什麼你需要密碼管理工具現代人一天下來需要輸入多少組密碼,工作與生活己經和密碼密不可分! 除了足夠全安的密碼,密碼記錄、儲存的方式又足夠安全嗎?密碼管理工具可以帶來什麼幫助呢? 為什麼你需要密碼管理工具 資安問題!!大多人說著沒做壞事不怕被偷資料、監聽。嚴重曝露出現代人的基本科技素養的低落和無知 🤯 密碼的使用無所不在!! 行動裝置的普及,APP 、手機遊戲、銀行帳戶所有和生活相關的東西都需要密碼!!facebook, line 只要打開 APP 也會輸入密碼只是他是自動輸入、一般情況不可視 (auth token) 一般人最常發生的密碼資安問題…

4 years ago

簡單使用 Mysql Partition 優化查詢

mysql 資料表分區 mysql table partition 從架構上調整 mysql 的查詢效率。mysql DB 的優化可以簡單也能複雜,除了調整設定值。也可以透過水平分割(Horizontal Partitioning)、垂直分割(Vertical Partitioning) 分庫或分表將資料分散儲存減少資料搜尋、group by 時的效能消耗。拆開批次處理,理論上效率都會變好,本文就水平分割的…

4 years ago