瀏覽分類:

使用 Laravel 打造 RESTful API

Laravel RESTful API 送養系統 完賽結語

未來展望

感謝有鐵人賽這個機會,讓我系統產生了一個雛形,還可以分享我目前知道的所見所聞,我會繼續完成這個系統,開始動手做前端的畫面,還有把系統規劃的更加完整,幫台灣的浪浪進一份心力,減少浪浪與人類的衝突,以及浪浪過多環境衛生的問題。

題外話:小弟我想專注在後端的開發,前端想外包,但因為只是想做一個作品,正在考慮要不要花這個錢,正在想要不要前端自己切版,淘寶買素材自已用就好還是外包給設計師畫圖(想讓前端畫面好看一點),甚至考慮整個前端都外包!因為以後想朝向後端、資料庫方面發展,所以想要一部分外包,不知道怎麼做會比較好!如果有經驗的歡迎跟我分享~或對動保議題有興趣的高手,也歡迎一起來做這個專案!

閱讀更多

Laravel 自動產生API文件

簡介&安裝

我們打造好的API,沒有使用手冊,對於要介接的開發者,根本無法使用,所以必須提供文件給他們!

所以今天就來介紹 mpociot/laravel-apidoc-generator 這是搭配apidoc + Laravel路徑配置 另外寫好的套件,能夠基於 Laravel 路由自動生成專案 API 文件,可以省掉很多麻煩!

也可以使用 apidoc 官方的套件但就是需要多設定一些路徑!

GitHub連結

使用Composer安裝這個套件

composer require --dev mpociot/laravel-apidoc-generator
閱讀更多

更好的自己更好的 API – 如何安心升級 Laravel6

昨天優化API讓我們在錯誤的經驗中不斷的學習,但也因為這些經驗,可能讓我們猶豫不敢前進,這會是內心一個很大的阻力,但也是自然的保護機制!

今天會有更大的改變,建議在嘗試練習的專案中可以嘗試,或是測試環境上測試,若用於正式上線的系統,請深思熟慮!並做好備份的動作~

系統要越來越好的關鍵條件

  1. 足夠量的測試覆蓋率(核心為主的程式碼測試,例如:對Service的測試)
  2. 安全性的更新(現在的系統,功能越來越大,撰寫的過程,時常都會用到套件!使用Laravel 框架也是,每個版本都會有安全漏洞維護的期限,為了系統安全建議更新,但更新後肯定會有一些錯誤產生,確保無誤一定要有測試程式保護)
  3. 良好的撰寫習慣,符合規定的Coding Style
  4. 確認官方升級文件的項目,在目前系統可能影響到的地方,手動確認程式無誤!
  5. 在測試環境升級確認無誤,再運用在線上系統,升級前一定要備份
閱讀更多

更好的自己更好的 API

今天來優化自己的 API (順便聊聊心情人生),前幾天都是把原本既有的程式碼拆開,現在要來優化API。

直接動手做(心情分享)

今天打算修改的部分希望盡量把原本的不足,寫成符合規範的程式碼!若你懶得看心情分享!請直接跳到下方的 修改原本設計的 URI單元,馬上實現動手做的精神!

人生難免不如意去年想要參加鐵人賽,但被一些事情影響到自己的心情,實在提不起勁,什麼也都懶得做、懶得用!沒有參加到去年的鐵人賽了

(現在出社會兩年多了!說實在真的沒有比當學生開心好好把握當學生 )。

那時心情比較低落所以看了很多書呀!心理學、正念、生活品質、斷捨離… 嘗試做很多改變。

什麼都試試看!最後成效不佳,覺得自己很廢。得到最大的體悟就是 現在認為的事情不一定是對的事,因此開始有點不敢動手做,覺得成效不好,做白工的感覺!

最後實在不行,覺得太廢了!跟朋友聊聊,發現如果遇到不同意見的人,可以在自己發表意見時先聽聽對方的想法,多多少少都會感覺得出來他為什麼這麼說的原因,換位思考一下!我覺得這很有幫助~

(雖然一件事情沒有絕對的對或錯!但是總比一直在做你以為對的事情,最後成效不佳好多了!)

現在看一看鐵人賽也快撐到完賽了!雖然不到完美但有很多收穫!

全部都歸咎於開始動手做,不開始就不會有進展,很開心我對於寫程式這方面充滿這種熱情! 哈哈哈xD

朋友跟我說,人生是一個面,工作是個點,我的人生只有工作跟運動,我現在是一條線而已,非常規律、自閉。 (工程師都這樣嗎?)

親情、友情、愛情,我好像都沒有顧好! 沒有像對程式般的熱情,那種撩下去就對了感覺!

如果你是害怕寫程式,撩下去就對了!(自己期許除了程式能力方面外,也有這樣的熱情。)

秉持著撩下去的熱情做做看就對了!沒有一次就寫到完美的Code,必須要有嘗試過的經驗,還有不斷的修正。

廢話不多馬上依照我目前的經驗分享,讓API更好維護,讓程式碼更符合統一規範的過程。

正式上線系統修改變更程式前請思考清楚!

閱讀更多

讓你的程式更美好 – Service後可以加入很多功能

今天我們繼續拆分程式碼!把商業邏輯的內容寫在 Service 檔案中,這過程中我們都沒有加入新功能,主要是把程式放適當的位置。

Service

Service檔案 必須手動新增,建立一個 AnimalService 專門來處理動物資源大大小小的商業邏輯。(這裡不包含外部API喔!只用來寫操作動物資源的邏輯!)

假設我今天想把 行政院農委會收容所認養公開資料 的API,接到我的送養平台,要另外寫一個 Service檔案喔!

我的另外一篇鐵人賽 後端前進PostgreSQL (鐵人賽連結) 系列,是在嘗試學習用 PostgreSQL 資料庫!整理、拆解這些農委會的認養公開資料以及PostgreSQL的介紹,有興趣的也可以看一下喔!

閱讀更多

讓你的程式更美好 – 重構現有的程式碼

開始重構程式碼,前幾天有提到 Controller 越來越肥大,程式碼越來越多,根本就已經超出人類想要看的範圍了!就像一篇好的文章,字數太多也是一件壞事,要有足夠的耐性才會想看。

這系列鐵人賽目前的 Controller 程式碼還不算太多,還算簡單拆開來相對容易,講解也比較清楚。

預計這樣拆開目前的 Controller

  • 驗證會員等級權限 – 已由 Policy 負責
  • 驗證使用者輸入資料 – 需再加入 Request
  • 商業邏輯或外部資源 – 需再加入 Service
  • 轉換資料結構 – 已由 Resource 負責

為了達到接近單一職責原則預計把Controller 拆成這個樣子! 降低程式之間的耦合性!對目前的程式來說比較好!檔案不會拆太多太細,又可以讓程式可讀性增加, PolicyResource 已經完成了!現在來拆解 Service驗證資料

閱讀更多

讓你的程式更美好 – 寫一點點測試

昨天簡單介紹一下 Service 怎麼那麼突然要寫測試!小弟我對於測試這東西也是超級初心者~但是因為維護上遇到了一些困擾,所以對於這方面開始暸解一下~

發現對於CI/CD 還蠻有興趣的,打算有時間的話可以嘗試看看有沒有機會導入公司的開發維護流程

因為遇到的困難

  • 因為需求變更修改輸出結果!發現一些必要值移除了,有些畫面顯示不出來~發生錯誤。
  • 改了這個功能沒事正常運作,但是改A壞B,另外一個功能因為有用到相關的值導致錯誤

因此來寫一點點測試吧!確保資料是我們要的樣子,測試輸出結果。

讓程式幫我們測試我們的功能,我們是開發API想必會給其他人介接API,跑測試若是減少到必要資料時就會提醒有錯誤,可以避免如果做了一些變動,不知道介接API的人用到哪些參數值,因為有測試確保錯誤的發生!

另外一個關鍵適當的用版本號控管,這必須看開發時的時間點,有不同的解決辦法,正式開發中的API就不用太在意URI的版本號了!正式上線後有人開始使用API,有改到資料的結構,建議直接用版本號去更新,就別動舊的API不然很多人用時,你可以會被很多人關心。

測試檔案命名規則

  1. 檔案一定要由Test結尾才會讀取得到!(例如下方產生的AnimalTest
  2. 檔案內的方法必須由test開頭才可以!

產生測試檔案

產生一個用來測試動物資源的測試檔案

php artisan make:test AnimalTest

準備來寫測試囉!打開 tests/Feature/AnimalTest.php

寫測試時間

這個檔案中,請自行對於想測試的動作做命名,要想想各種可能,例如我想要測試查詢動物的API,因為查看動物不需要任何權限,因此我們的程式碼相對比較簡單,我們繼續看下去吧!

測試查詢 animal 結構

/**
* 測試查看animal 列表的 json 格式
*
* @return void
*/
public function testViewAllAnimal()
{
    //請求 api/animal 結果存入 $response
    $response = $this->get('api/animal');

    //assertJsonStructure 判斷 Json 結構是否與我們下方的結構相同
    $response->assertJsonStructure([
        "current_page",
        "data" => [
            [
                "id",
                "type_id",
                "name",
                "birthday",
                "area",
                "fix",
                "description",
                "personality",
                "created_at",
                "updated_at",
                "user_id"
            ]
        ],
        "first_page_url",
        "from",
        "last_page",
        "last_page_url",
        "next_page_url",
        "path",
        "per_page",
        "prev_page_url",
        "to",
        "total",
    ]);
}

這時候你會發現左側測試套件的工具列會出現tests/Feature/AnimalTest.php 並且可以點開 有testViewAllAnimal 方法! 如下圖灰色圖示的兩個項目

套件畫面

點選 三角形執行測試,如果程式寫對,輸出結果跟剛剛撰寫的測試結構一樣,就會顯示綠色勾勾!

套件畫面

再來想想有什麼需要測試

測試創建 animal 資源

在新建前因為確保每次測試完都可以成功,不是跑第一次後第二次就不成功,或是這台機器可以跑並且全數通過,但其他機器不能跑的情況!

Laravel 有一個方便的重置資料庫的trait,不過這是會直接執行 php artisan migrate:refresh 初始化資料庫「請勿正式環境使用不然你會後悔

use Illuminate\Foundation\Testing\RefreshDatabase;

class AnimalTest extends TestCase
{
    use RefreshDatabase;

    //...
}

另外一種是 DatabaseTransactions 他是使用資料庫 Transactions 執行完後並不會提交,會rollback ,所以只會還原這是的變更!我另外一系列的鐵人賽有講到這個在附上連結!

所以我們不用上面的RefreshDatabase用DatabaseTransactions 請自行依照你的測試流程斟酌使用

use Illuminate\Foundation\Testing\DatabaseTransactions;

class AnimalTest extends TestCase
{
    use DatabaseTransactions;

    //...
}

測試有權限有效 token創建資源

因為創建這部分,管理員跟一般會員都可以操作所以寫一個就好,Passport 套件有一個方法讓我們可以模擬權限

先在tests/Feature/AnimalTest.php新建一個 testCanCreateAnimal() 我先把官方網站的範例複製過來,修改成新建動物的請求POST /api/animal其他先不改,儲存並點選執行測試的三角形按鈕,除了工具列的顯示,還會發現錯誤標示於錯誤的方法上。

測試錯誤

錯誤訊息的意思是說測試結果請求POST /api/animal 回傳 401 HTTP 狀態碼,不是 201 新建成功的狀態碼。

因為我們還沒加上模擬權限的部分,請如下修改


    /**
    * 測試建立animal
    *
    * @return void
    */
    public function testCanCreateAnimal()
    {
        Passport::actingAs(
            User::first(),
            ['*']
        );

        // 請求時並傳入資料
        $response = $this->json(
            'POST', 'api/animal', 
            [
                'type_id' => '1',
                'name' => '大黑',
                'birthday' => '2019-10-05', //今天要補班
                'area' => '台北市',
                'fix' => '1'
            ]
        );
        
        //檢查返回資料
        $response->assertStatus(201)  //狀態碼應屬於201
            ->assertJson(
                [
                    "type_id"=> "1",
                    "name"=>"大黑",
                    "birthday"=>"2019-10-05",
                    "area"=>"台北市",
                    "fix"=>"1"
                ]
            );
    }

順利通過測試,這邊用 assertJson 來檢查回傳資料是否完全符合,裡面沒有包含到的就不會去檢查,例如他會回傳 createdat、updatedat、id 沒有寫在這個陣列裡,就不會去檢查它的值,這點必須留意一下。

測試沒有有效 token 操作 測試

多增加一個 testCanNotCreateAnimal 方法,程式碼如下所示

    /**
     * 測試不能建立animal
     *
     * @return void
     */
    public function testCanNotCreateAnimal()
    {
        // 沒有模擬會員權限的程式

        // 請求時並傳入資料
        $response = $this->json(
            'POST', 'api/animal', 
            [
                'type_id' => '1',
                'name' => '大黑',
                'birthday' => '2019-10-05', //今天要補班
                'area' => '台北市',
                'fix' => '1'
            ]
        );
        
        //檢查返回資料
        $response->assertStatus(401)  //沒有token,狀態碼應屬於401
            ->assertJson(
                [
                    "message" => "Unauthenticated."
                ]
            );
    }

其他想到可以測試的功能

大部分都是這樣寫,以此類推,主要是要想辦法讓每一台伺服器跑測試的結果都一樣,並不是這台測試正確就好。以下列出還可以寫的測試,有興趣可以多多嘗試,這裡不一一列出程式碼。

  • 更新 animal 測試
    • 測試 管理員 更新
    • 測試 一般會員 更新
    • 測試 沒有有效 token 操作 更新
  • 刪除 animal 測試
    • 測試管理員 刪除
    • 一般會員 刪除
    • 沒有有效 token 操作 測試

存檔自動測試

如果你是自己撰寫程式碼多多少少會有錯誤,一直按三角形執行測試是不是覺得很煩呀~ 工程師就是最不喜歡重複的動作了!這個套件可以監測檔案儲存,自動執行測試喔!

套件畫面

現在只要儲存就會自動跑測試~ 爽~~

結論

寫測試有涵蓋率這種東西,沒有寫到測試的地方還是測不到,但我覺得核心有顧好!錯誤自然就會減少!大家一起加油吧~我也在學習,再次強調,小弟我這方面非常淺,歡迎給我任何回應!可以讓我作為改善的參考!或有什麼推薦的教學也歡迎跟我分享喔! 感謝

參考資料

Passport 模擬權限

Laravel官方測試文件

讓你的程式更美好 – Service 概念

我自己的經驗呢!是把原生的PHP轉換成Laravel框架,那個時候最主要希望可以好維護,但是,把權限啦~商業邏輯啦~全部都會寫在Controller 最後你就會發現

Controller 越來越大

Controller 越來越大

Controller 越來越大

如果又不是前後端分離的方式拆開的話,Controller 會非常非常亂。

之前就開始想辦法前後端拆開,所以開始研究RESTful API 的設計方式

閱讀更多

進階 RESTful API 討論

複習一下!並加入比較深入進階的部分,利用鐵人賽這個機會讓我再去認真查詢學習 RESTful API 的相關設計!雖然不是強制一定要這麼設計API,但是可以讓程式碼的可讀性更好!我想這是各位大大會想努力的地方。

確認一個資源

如之前的範例資源就是動物資源,設計RESTful API要先有一個客戶端資源,可以做查詢動物的資訊、建立、編輯、刪除,分別用HTTP不同的動詞,以客戶端(介接我們API的人)的方向去思考,不需要跟資料表一模一樣。

HTTP 動詞

  • GET: 讀取資源
  • POST: 新增資源
  • PUT: 替換資源
  • DELETE: 刪除資源
  • PATCH: 更新資源部份內容

GET 的動作相較安全,它不會變動更改到伺服器的資訊,主要用來查詢資料。

POST、DELETE、PATCH、PUT 則會依照對應的動詞做需要的動作,寫入資料庫,或一些商業邏輯。

一定會是這種模式 動詞+資源

POST http://127.0.0.1/animal

PUT、PATCH 差別

PUT 通常做替換一個資源功能。

PATCH 修改資源的部分內容。

我自己是這麼定義的,假設資料表內已經有一筆資料內容如下

{
  "id" : 1,
  "name" : "小白" ,
  "type" : "小型犬" ,
  "birthday" : "2019/1/29"
}

PUT : 動物資料整個替換掉 PUT 方式請求網址 /animals/1  修改編號1的資料,回傳資料內容都是ID 1但裡面的內容整個不同。

PUT下面的內容,那麼ID 1的資料就會全部被修改成小黑的資訊,所以請求的時候必須填寫所有欄位不然資料會變成預設值。

{
  "name":"小黑" ,
  "type":"大型犬",
}

--結果--
{
  "id" : 1,
  "name" : "小黑" ,
  "type" : "大型犬" ,
  "birthday" : null
}
閱讀更多

我的最愛追蹤功能製作

定義資源

我的最愛功能,製作一個可以讓 user 追蹤動物的操作,是一個連結的關係,綁定動物與用戶的關聯。

依照以前的經驗,我會幫這樣的動作取一個名字 like 之類的資料表來儲存內容。

但經過幾次的打造API經驗後,在規劃資料表的命名上,如果系統規模很大只有 like 當表名不是很明確。

我們這個系列打造的送養系統如果想要新增一個追蹤某位愛心媽媽的功能,就會覺得like不是很明確。

這樣在資料庫中看到 like 資料表,無法明確的知道內容。所以這邊我不另外給它一個名字。

會製作一張表  animal_user  這是我目前的原則!可以清楚知道這張資料表紀錄著 animal 與 user 的關係,並且依照字母排列A->Z命名這張表。 所以不命名為 user_animal 這是開始用 Laravel 後才有的習慣,在某個官方文章有寫到預設是 開頭A->Z來建立資料表。

閱讀更多