聊聊Laravel中怎么用Saloon進行API集成

laravel中怎么用saloon進行api集成?下面本篇文章給大家介紹一下在laravel中使用saloon進行api集成的方法,希望對大家有所幫助!

聊聊Laravel中怎么用Saloon進行API集成

我們都去過那里,我們想與 Laravel 中的第三方 API 集成,我們問自己「我應該怎么做?」。 談到 API 集成,我并不陌生,但每次我都想知道什么是最好的方法。 Sam Carré 于 2022 年初構建了一個 Sam Carré,名為 Sam Carré,這可以使我們的 API 集成令人驚嘆。 然而,這篇文章將會非常不同,這將是一個關于如何使用它從頭開始構建集成的演練。

像所有偉大的事情一樣,它以laravel new 開始并從那里開始,所以讓我們開始吧。 現在在安裝 Laravel 時,你可以使用 laravel installer 或 composer ——這部分由你決定。 如果可以的話,我會推薦安裝程序,因為它提供了簡單的選項來做更多的事情,而不僅僅是創建一個項目。 創建一個新項目并在您選擇的代碼編輯器中打開它。 一旦我們在那里,我們就可以開始了。

我們要建造什么? 我很高回答這個提問! 我們將構建與 github API 的集成,以獲取可用于 repo 的工作流列表。 現在,如果你像我一樣在命令行上花費大量時間,這可能會非常有用。 你正在開發一個應用程序,將更改推送到一個分支或創建一個 PR – 它通過一個可能正在運行許多其他事情之一的工作流。 了解此工作流程的狀態有時會對您接下來的工作產生巨大影響。 功能齊全嗎? 我們的工作流程運行是否存在問題? 我們的測試或靜態分析是否通過了? 所有這些你通常會等待并檢查 GitHub 上的 repo 以查看狀態。 此集成將允許您運行 artisan 命令,獲取 repo 的可用工作流列表,并允許你觸發新的工作流運行。

所以到現在為止,composer 應該已經完成了它的工作并安裝了一個完美的起點,一個 Laravel 應用程序。 接下來我們需要安裝 Saloon – 但我們要確保安裝 laravel 版本,所以在終端中運行以下命令:

composer?require?sammyjo20/saloon-laravel

就像這樣,我們已經離更容易的集成更近了一步。 如果你在此階段有任何問題,請確保檢查您正在使用的 Laravel 和 php 版本,因為 Saloon 至少需要 Laravel 8 和 PHP 8!

所以,現在我們已經安裝了 Saloon,我們需要創建一個新類。 在 Saloons 術語中,這些是「連接器」,連接器所做的一切就是創建一種以對象為中心的方式來表達 – 此 API 通過此類連接。 有一個方便的 artisan 命令允許您創建這些,因此運行以下 artisan 命令來創建 GitHub 連接器:

php?artisan?saloon:connector?GitHub?GitHubConnector

該命令分為兩部分,第一個參數是你正在創建的集成,第二個參數是要創建的連接器的名稱。這意味著你可以為集成創建多個連接器 – 如果需要的話可以通過多種不同方式進行連接。

這將在 app/http/Integrations/GitHub/GitHubConnector.php 下為你創建一個新類,讓我們看一下,了解發生了什么。

我們看到的第一件事是我們的連接器擴展了「SaloonConnector」,這將使我們能夠讓我們的連接器在沒有大量樣板代碼的情況下工作。然后我們繼承了一個名為「Acceptsjson」的特征。現在,如果我們查看 Saloon 文檔,我們知道這是一個插件。這基本上為我們的請求添加了一個標頭,告訴第 3 方 API 我們想要接受 JSON 響應。接下來我們看到的是我們有一個方法來定義我們的連接器的基本 URL – 所以讓我們添加我們的:

public?function?defineBaseUrl():?string { ????return?'https://api.github.com'; }

又好又干凈,我們甚至可以更進一步,這樣我們就可以處理應用程序中較少的松散字符串 – 所以讓我們看看我們如何做到這一點。 在您的 config/services.php 文件中添加新的服務記錄:

'github'?=>?[ ????'url'?=>?env('GITHUB_API_URL',?'https://api.github.com'), ]

這將允許我們在不同的環境中覆蓋它 – 為我們提供更好和更可測試的解決方案。 在本地,我們甚至可以使用他們的 OpenAPI 規范模擬 GitHub API,并對其進行測試以確保其正常工作。 但是,本教程是關于 Saloon 的,所以我離題了……現在讓我們重構我們的基本 URL 方法以使用配置:

public function defineBaseUrl(): string {     return (string) config('services.github.url'); }

如你所見,我們現在從配置中獲取新添加的記錄 – 并將其轉換為字符串以確保類型安全 – config() 可能會返回多種不同類型的結果。如果可以的話,我們希望對此進行嚴格處理。

接下來我們有默認 header 和默認配置,無須擔心默認 header 的內容,因為我們將在一段時間內自行處理身份驗證。但配置部分是我們可以為集成定義 guzzle 選項的地方,因為 Saloon 在服務引擎下使用了 Guzzle。現在讓我們設置超時并繼續,我們需要花一些時間配置它:

public function defaultConfig(): array {     return [         'timeout' => 30,     ]; }

我們現在已經按照我們的需要配置了我們的連接器,如果我們有需要添加的配置,可以稍后再添加。下一步是開始考慮我們要發送的請求。如果我們查看 GitHub Actions API 的 API 文檔,我們有很多選擇,我們將從列出特定存儲庫的工作流開始:/repos/{owner}/{repo}/actions/workflows。運行以下 artisan 命令創建一個新請求:

php artisan saloon:request GitHub ListRepositoryWorkflowsRequest

同樣,第一個參數是集成,第二個參數是我們要創建的請求的名稱。我們需要確保為我們正在創建的請求命名集成,以便它存在于正確的位置,然后我們需要給它一個名稱。我將我的命名為 ListRepositoryWorkflowsRequest,因為我喜歡描述性的命名方法 – 但是,你可以隨意調整以適應你喜歡的命名方式。這將創建一個新文件供我們查看:app/Http/Integrations/GitHub/Requests/ListRepositoryWorkflowsRequest.php – 現在讓我們看一下。

我們再次在這里擴展了一個庫類,這次是預期的 SaloonRequest。這里會包含一個連接器屬性和一個方法。如果需要,我們可以修改這個方法 – 但默認的 GET 是我們現在需要的。然后我們有一個定義端點的方法。重構你的請求類,使其類似于以下示例:

?class?ListRepositoryWorkflowsRequest?extends?SaloonRequest { ????protected??string?$connector?=?GitHubConnector::class;  ????protected??string?$method?=?Saloon::GET;  ????public?function?__construct( ????????public?string?$owner, ????????public?string?$repo, ????)?{}  ????public?function?defineEndpoint():?string ????{ ????????return?"/repos/{$this->owner}/{$this->repo}/actions/workflows"; ????} }

我們所做的是添加一個構造函數,它接受 repo 和 owner 作為參數,然后我們可以在端點定義方法中使用它們。我們還將連接器設置為我們之前創建的 GitHubConnector。所以我們有一個我們知道可以發送的請求,我們可以從集成中走一小步,轉而考慮控制臺命令。

如果你之前沒有在 Laravel 中創建過控制臺命令,請務必查看 文檔。運行以下 artisan 命令來為此集成創建第一個命令:

php?artisan?make:command?GitHub/ListRepositoryWorkflows

這將創建以下文件:app/console/Commands/GitHub/ListRespositoryWorkflows.php。我們現在可以開始使用命令來發送請求并獲取我們關心的數據。當談到控制臺命令時,我總是做的第一件事就是考慮簽名。我希望如何調用它?它需要能夠解釋它正在做什么,同時具備一定的辨識度。我將會用 github:workflows 作為簽名,因為這很好地解釋了我想做的事情。我們還可以向控制臺命令添加描述,以便在瀏覽可用命令時更好地解釋目的:「通過存儲庫名稱從 GitHub 獲取工作流列表」。

最后,我們到了命令的 handle 方法,這部分是我們實際需要做的事情。在我們的例子中,我們將發送一個請求,獲取一些數據并以某種方式顯示這些數據。然而,在我們能夠做到這一點之前,我們還沒有完成一件事。那就是身份驗證。

對于每一個 API 集成,身份驗證都是關鍵方面之一——我們需要 API 不僅知道我們是誰,而且知道我們實際上被允許發出這個請求。如果你轉到 你的 GitHub 設置 并點擊進入開發人員設置和個人訪問令牌,在此你可以生成自己的設置。我建議使用這種方法,而不是為此使用完整的 OAuth 應用程序。我們不需要 OAuth,我們只需要用戶能夠訪問他們需要的內容。

獲得訪問令牌后,我們需要將其添加到我們的 .env 文件中,并確保我們可以通過配置提取它。

GITHUB_API_TOKEN=ghp_loads-of-letters-and-numbers-here

我們現在可以在 github 下的 config/services.php 中擴展我們的服務,添加這個令牌:

'github'?=>?[ ????'url'?=>?env('GITHUB_API_URL',?'https://api.github.com'), ????'token'?=>?env('GITHUB_API_TOKEN'), ]

現在我們有了一個加載這個令牌的好方法,我們可以回到我們的控制臺命令!我們需要修改我們的簽名以允許我們接受所有者和存儲庫作為參數:

?class?ListRepositoryWorkflows?extends?Command { ????protected?$signature?=?'github:workflows ????????{owner?:?The?owner?or?organisation.} ????????{repo?:?The?repository?we?are?looking?at.} ????';  ????protected?$description?=?'Fetch?a?list?of?workflows?from?GitHub?by?the?repository?name.';  ????public?function?handle():?int ????{ ????????return?0; ????} }

現在我們可以將注意力轉移到 handle 方法上:

public?function?handle():?int { ????$request?=?new?ListRepositoryWorkflowsRequest( ????????owner:?$this->argument('owner'), ????????repo:?$this->argument('repo'), ????);  ????return?self::SUCCESS; }

在這里,我們開始通過將參數直接傳遞到請求本身來構建我們的請求,但是我們可能想要做的是創建一些局部變量來提供一些控制臺反饋:

?public?function?handle():?int { ????$owner?=?(string)?$this->argument('owner'); ????$repo?=?(string)?$this->argument('repo');  ????$request?=?new?ListRepositoryWorkflowsRequest( ????????owner:?$owner, ????????repo:?$repo, ????);  ????$this->info( ????????string:?"Fetching?workflows?for?{$owner}/{$repo}", ????);  ????return?self::SUCCESS; }

所以我們有一些反饋給用戶,這對于控制臺命令來說總是很重要的。現在我們需要添加我們的身份驗證令牌并實際發送請求:

?public?function?handle():?int { ????$owner?=?(string)?$this->argument('owner'); ????$repo?=?(string)?$this->argument('repo');  ????$request?=?new?ListRepositoryWorkflowsRequest( ????????owner:?$owner, ????????repo:?$repo, ????);  ????$request->withTokenAuth( ????????token:?(string)?config('services.github.token'), ????);  ????$this->info( ????????string:?"Fetching?workflows?for?{$owner}/{$repo}", ????);  ????$response?=?$request->send();  ????return?self::SUCCESS; }

如果你修改上述內容并在 $response->json() 上執行 dd(),然后運行命令:

php?artisan?github:workflows?laravel?laravel

這將獲得 laravel/laravel repo 的工作流列表。我們的命令將允許你使用任何公共存儲庫,如果你希望它更具體,你可以建立一個要檢查的存儲庫選項列表,而不是接受參數 —— 但這部分取決于你個人。對于本教程,我將重點關注更廣泛更開放的用例。

現在,我們從 GitHub API 得到的響應非常好且信息豐富,但它需要轉換才能顯示,如果我們孤立地查看它,則沒有上下文。相反,我們將在我們的請求中添加另一個插件,這將允許我們將響應轉換為 DTO(域傳輸對象),這是處理此問題的好方法。它將允許我們放松我們習慣于從 API 獲取的靈活數組,并獲得更具上下文感知的東西。讓我們為工作流創建一個 DTO,創建一個新文件:app/Http/Integrations/GitHub/DataObjects/Workflow.php 并向其中添加以下代碼:

?class?Workflow { ????public?function?__construct( ????????public?int?$id, ????????public?string?$name, ????????public?string?$state, ????)?{}  ????public?static?function?fromSaloon(array?$workflow):?static ????{ ????????return?new?static( ????????????id:?intval(data_get($workflow,?'id')), ????????????name:?strval(data_get($workflow,?'name')), ????????????state:?strval(data_get($workflow,?'state')), ????????); ????}  ????public?function?toArray():?array ????{ ????????return?[ ????????????'id'?=>?$this->id, ????????????'name'?=>?$this->name, ????????????'state'?=>?$this->state, ????????]; ????} }

我們有一個構造函數,其中包含我們要顯示的工作流的重要部分,一個 fromSaloon 方法,它將一個數組從一個 saloon 轉換為一個新的 DTO,以及一個用于將 DTO 顯示回數組的數組方法當我們需要它時。在我們的ListRepositoryWorkflowsRequest 中,我們需要繼承一個新特征并添加一個新方法:

?class?ListRepositoryWorkflowsRequest?extends?SaloonRequest { ????use?CastsToDto;  ????protected??string?$connector?=?GitHubConnector::class;  ????protected??string?$method?=?Saloon::GET;  ????public?function?__construct( ????????public?string?$owner, ????????public?string?$repo, ????)?{}  ????public?function?defineEndpoint():?string ????{ ????????return?"/repos/{$this->owner}/{$this->repo}/actions/workflows"; ????}  ????protected?function?castToDto(SaloonResponse?$response):?Collection ????{ ????????return?(new?Collection( ????????????items:?$response->json('workflows'), ????????))->map(function?($workflow):?Workflow?{ ????????????return?Workflow::fromSaloon( ????????????????workflow:?$workflow, ????????????); ????????}); ????} }

我們繼承了 CastsToDto trait,它允許這個請求在響應中調用 dto 方法,然后我們添加一個 castToDto 方法,我們可以控制它的轉換方式。我們希望它返回一個新的集合,因為有多個工作流,使用響應正文的工作流部分。然后我們映射集合中的每個項目 – 并將其轉換為 DTO。現在我們既可以這樣做,也可以使用 DTO 構建集合:

protected?function?castToDto(SaloonResponse?$response):?Collection { ????return?new?Collection( ????????items:?$response->collect('workflows')->map(fn?($workflow)?=> ????????????Workflow::fromSaloon( ????????????????workflow:?$workflow ????????????), ????????) ????); }

你可以在這里選擇最適合你的方式。我個人更喜歡第一種方法,因為我喜歡逐步了解邏輯,但是這兩種方法都沒有錯——選擇權在你。現在回到命令,我們現在需要考慮我們希望如何顯示這些信息:

public?function?handle():?int { ????$owner?=?(string)?$this->argument('owner'); ????$repo?=?(string)?$this->argument('repo');  ????$request?=?new?ListRepositoryWorkflowsRequest( ????????owner:?$owner, ????????repo:?$repo, ????);  ????$request->withTokenAuth( ????????token:?(string)?config('services.github.token'), ????);  ????$this->info( ????????string:?"Fetching?workflows?for?{$owner}/{$repo}", ????);  ????$response?=?$request->send();  ????if?($response->failed())?{ ????????throw?$response->toException(); ????}  ????$this->table( ????????headers:?['ID',?'Name',?'State'], ????????rows:?$response ????????????->dto() ????????????->map(fn?(Workflow?$workflow)?=> ??????????????????$workflow->toArray() ????????????)->toArray(), ????);  ????return?self::SUCCESS; }

因此,我們創建一個帶有標題的表,然后對于我們想要響應 DTO 的行,我們將映射返回的集合,將每個 DTO 轉換回要顯示的數組。從響應數組轉換為 DTO 再轉換回數組,這似乎違反直覺,但這會強制執行類型,以便 ID、名稱和狀態在預期時始終存在,并且不會給出任何有趣的結果.它允許正常響應數組可能沒有它的一致性,如果我們愿意,我們可以將它轉換為一個值對象,我們可以在其中附加行為。如果我們現在運行我們的命令,我們現在應該會看到一個漂亮的表格輸出,它比幾行字符串更容易閱讀:

php?artisan?github:workflows?laravel?laravel
Fetching?workflows?for?laravel/laravel +----------+------------------+--------+ |?ID???????|?Name?????????????|?State??| +----------+------------------+--------+ |?12345678?|?pull?requests????|?active?| |?87654321?|?Tests????????????|?active?| |?18273645?|?update?changelog?|?active?| +----------+------------------+--------+

最后,僅僅列出這些工作流程是很棒的——但讓我們以科學的名義更進一步。假設你正在針對你的一個存儲庫運行此命令,并且想手動運行更新更改日志?或者,也許你希望使用你的實時生產服務器或你可能想到的任何事件在 cron 上觸發它?我們可以將變更日志設置為每天午夜運行一次,這樣我們就可以在變更日志中獲得每日回顧或任何我們可能想要的內容。讓我們創建另一個控制臺命令來創建一個新的工作流調度事件:

php?artisan?saloon:request?GitHub?CreateWorkflowDispatchEventRequest

在這個新文件 app/Http/Integrations/GitHub/Requests/CreateWorkflowDispatchEventRequest.php 中添加以下代碼,以便我們瀏覽它:

class?CreateWorkflowDispatchEventRequest?extends?SaloonRequest { ????use?HasJsonBody;  ????protected??string?$connector?=?GitHubConnector::class;  ????public?function?defaultData():?array ????{ ????????return?[ ????????????'ref'?=>?'main', ????????]; ????}  ????protected??string?$method?=?Saloon::POST;  ????public?function?__construct( ????????public?string?$owner, ????????public?string?$repo, ????????public?string?$workflow, ????)?{}  ????public?function?defineEndpoint():?string ????{ ????????return?"/repos/{$this->owner}/{$this->repo}/actions/workflows/{$this->workflow}/dispatches"; ????} }

通過設置連接器,并繼承 HasJsonBody 特征以允許我們發送數據。該方法已設置為 POST 請求,因為我們要發送數據。然后我們有一個構造函數,它接受構建端點的 URL 部分。

最后,我們在 defaultData 中有圓頂默認數據,我們可以使用它來設置此發布請求的默認值。與 repo 一樣,我們可以在此處傳遞提交哈希或分支名稱 – 所以我將默認設置為 main,因為這就是我通常所說的生產分支。

我們現在可以觸發這個端點來調度一個新的工作流事件,所以讓我們創建一個控制臺命令來控制它,這樣我們就可以從我們的 CLI 運行它:

php?artisan?make:command?GitHub/CreateWorkflowDispatchEvent

現在讓我們編寫具體的邏輯,我們可以了解正在發生的事情:

class?CreateWorkflowDispatchEvent?extends?Command { ????protected?$signature?=?'github:dispatch ????????{owner?:?The?owner?or?organisation.} ????????{repo?:?The?repository?we?are?looking?at.} ????????{workflow?:?The?ID?of?the?workflow?we?want?to?dispatch.} ????????{branch??:?Optional:?The?branch?name?to?run?the?workflow?against.} ????';  ????protected?$description?=?'Create?a?new?workflow?dispatch?event?for?a?repository.';  ????public?function?handle():?int ????{ ????????$owner?=?(string)?$this->argument('owner'); ????????$repo?=?(string)?$this->argument('repo'); ????????$workflow?=?(string)?$this->argument('workflow');  ????????$request?=?new?CreateWorkflowDispatchEventRequest( ????????????owner:?$owner, ????????????repo:?$repo, ????????????workflow:?$workflow, ????????);  ????????$request->withTokenAuth( ????????????token:?(string)?config('services.github.token'), ????????);  ????????if?($this->hasArgument('branch'))?{ ????????????$request->setData( ????????????????data:?['ref'?=>?$this->argument('branch')], ????????????); ????????}  ????????$this->info( ????????????string:?"Requesting?a?new?workflow?dispatch?for?{$owner}/{$repo}?using?workflow:?{$workflow}", ????????);  ????????$response?=?$request->send();  ????????if?($response->failed())?{ ????????????throw?$response->toException(); ????????}  ????????$this->info( ????????????string:?'Request?was?accepted?by?GitHub', ????????);  ????????return?self::SUCCESS; ????} }

就像在我們有簽名和描述之前一樣,這次我們的簽名有一個可選的分支,以防我們想要覆蓋請求中的默認值。所以在我們的處理方法中,我們可以簡單地檢查輸入是否有參數 branch,如果有,我們可以解析它并為請求設置數據。然后我們向 CLI 提供一些反饋,讓用戶知道我們在做什么 – 并發送請求。如果此時一切順利,我們可以簡單地輸出一條消息,通知用戶 GitHub 接受了請求。但是,如果出現問題,我們希望拋出特定的異常,至少在開發過程中是這樣。

最后一個請求的主要警告是,我們的工作流程設置為通過在工作流程中添加一個新的 on 項目來由 webhook 觸發:

on:?workflow_dispatch

這就對了!我們使用 Saloon 和 Laravel 不僅列出存儲庫工作流程,而且如果配置正確,我們還可以觸發它們按需運行:muscle:

正如我在本教程開始時所說的,有很多方法可以實現 API 集成,但有一點是肯定的 – 使用 Saloon 使它變得干凈和簡單,而且使用起來也非常愉快。

原文地址:https://laravel-news.com/api-integrations-using-saloon-in-laravel譯文地址:https://learnku.com/laravel/t/69007

【相關推薦:Sam Carré

? 版權聲明
THE END
喜歡就支持一下吧
點贊15 分享