如何使用Laravel的內建客戶端與外部API互動

如何使用Laravel的內建客戶端與外部API互動

Laravel使API互動對新的和有經驗的Web開發人員來說都是輕而易舉的。Larvel的HTTP客戶端是建立在PHP的Guzzle HTTP客戶端之上,讓開發者在進行HTTP請求時有更順暢的體驗。它的主要功能包括認證, 路由, 和有效的物件關係對映(ORM).

本文將探討如何使用Laravel的HTTP客戶端來進行請求, 除錯響應, 建立中介軟體和巨集, 以及更多。

  1. Laravel HTTP客戶端為你的API工作
  2. 前提條件
  3. 如何發出請求
  4. 併發請求
  5. 請求巨集
  6. 如何解碼響應
  7. 如何測試JSON APIs
  8. 如何處理事件

Laravel HTTP客戶端為你的API工作

Guzzle是一個簡單的PHP的HTTP客戶端。它為不同的表單請求提供了功能,包括 GETPOSTPUT, 和 DELETE ,以及流媒體功能和多部分請求。使用Guzzle HTTP客戶端,可以向伺服器傳送同步和非同步的請求。此外,它還配備了體面的中介軟體來定製客戶端的行為。

Laravel的HTTP客戶端是一個建立在Guzzle基礎上的封裝器,但具有額外的功能。它包括支援重試失敗的請求和一些JSON資料的輔助功能。Laravel HTTP客戶端的大部分功能都與Guzzle類似。

前提條件

在下面的章節中, 你會了解到更多關於Laravel的HTTP客戶端。要繼續學習, 你需要:

  • 有關Laravel, PHP, 和API的基本知識
  • 安裝了PHP和Composer
  • Postman

如何發出請求

要了解如何使用HTTP客戶端來發出請求, 你可以利用大量的託管API, 如ReqRes.

首先,匯入建立應用程式時包含的HTTP包。在App/Http/Controllers/UserController.php檔案中,新增以下程式碼,從檔案開頭的use語句開始,其餘程式碼在index函式中。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
use Illuminate\Support\Facades\Http;
return Http::get("https://reqres.in/api/users?page=2");
use Illuminate\Support\Facades\Http; return Http::get("https://reqres.in/api/users?page=2");
use Illuminate\Support\Facades\Http;
return Http::get("https://reqres.in/api/users?page=2");

Note: 對於複雜的用例,你也可以通過使用 withHeaders 方法傳送帶標頭檔案的請求。

在同一個檔案中,使用下面的程式碼建立一個新的方法帖子:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function post()
{
$response = Http::withHeaders([
'Content-Type' => 'application/json',
])->post('https://reqres.in/api/users', [
'name' => 'morpheus',
'job' => 'leader',
]);
return $response;
}
function post() { $response = Http::withHeaders([ 'Content-Type' => 'application/json', ])->post('https://reqres.in/api/users', [ 'name' => 'morpheus', 'job' => 'leader', ]); return $response; }
function post()
{
$response = Http::withHeaders([
'Content-Type' => 'application/json',
])->post('https://reqres.in/api/users', [
'name' => 'morpheus',
'job' => 'leader',
]);
return $response;
}

然後在routes/web.php檔案中為其新增一個路由:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Route::get('post',[UserController::class,'post']);
Route::get('post',[UserController::class,'post']);
Route::get('post',[UserController::class,'post']);

現在,可以用Postman來測試這個路由。開啟Postman,新增http://127.0.0.1:8000/post 作為URL,請求型別為 GET 。一旦你點選send,你會看到下面的響應:

使用Postman發出請求

使用Postman發出請求

並行請求

併發請求可以顯著提高效能,因為你可以在同一時間段內獲取更多的資料。Laravel的HTTP客戶端使得使用pool方法進行併發請求成為可能。

App/Http/Controllers/UserController.php裡面, 新增以下程式碼:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
use Illuminate\Http\Client\Pool;
function concurrent()
{
$responses = Http::pool(fn (Pool $pool) => [
$pool->get('https://reqres.in/api/users?page=2'),
$pool->get('https://reqres.in/api/users/2'),
$pool->get('https://reqres.in/api/users?page=2'),
]);
return $responses[0]->ok() &&
$responses[1]->ok() &&
$responses[2]->ok();
}
use Illuminate\Http\Client\Pool; function concurrent() { $responses = Http::pool(fn (Pool $pool) => [ $pool->get('https://reqres.in/api/users?page=2'), $pool->get('https://reqres.in/api/users/2'), $pool->get('https://reqres.in/api/users?page=2'), ]); return $responses[0]->ok() && $responses[1]->ok() && $responses[2]->ok(); }
use Illuminate\Http\Client\Pool;
function concurrent()
{
$responses = Http::pool(fn (Pool $pool) => [
$pool->get('https://reqres.in/api/users?page=2'),
$pool->get('https://reqres.in/api/users/2'),
$pool->get('https://reqres.in/api/users?page=2'),
]);
return $responses[0]->ok() &&
$responses[1]->ok() &&
$responses[2]->ok();
}

然後,在routes/web.php檔案中新增支援性路由。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Route::get('concurrent',[UserController::class,'concurrent']);
Route::get('concurrent',[UserController::class,'concurrent']);
Route::get('concurrent',[UserController::class,'concurrent']);

瀏覽器在訪問該路由時,會給出如下響應:

併發請求

併發請求

請求巨集

請求巨集在與常見的API路徑進行互動時非常有用。

要建立巨集,你需要使用下面的程式碼在App/Http/Controllers/UserController.php檔案的啟動方法內定義巨集:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
use Illuminate\Support\Facades\Http;
Http::macro('reqres', function () {
return Http::baseUrl('https://reqres.in/api');
});
use Illuminate\Support\Facades\Http; Http::macro('reqres', function () { return Http::baseUrl('https://reqres.in/api'); });
use Illuminate\Support\Facades\Http;
Http::macro('reqres', function () {
return Http::baseUrl('https://reqres.in/api');
});

Note:請確保在檔案的開頭新增使用語句。

然後,在 UserController 裡面使用這個巨集,新增以下程式碼:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function macro()
{
$response = Http::reqres()->get('/users?page=2');
return $response;
}
function macro() { $response = Http::reqres()->get('/users?page=2'); return $response; }
function macro()
{
$response = Http::reqres()->get('/users?page=2');
return $response;
}

正如你所看到的,因為巨集已經被建立了,你不必再新增完整的URL。

最後,使用下面的程式碼在routes/web.php檔案中新增一個路由:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Route::get('macro',[UserController::class,'macro']);
Route::get('macro',[UserController::class,'macro']);
Route::get('macro',[UserController::class,'macro']);

巨集請求

巨集請求

如何對響應進行解碼

要解碼一個響應並確保一個API請求是成功的,你可以使用客戶端中的status方法。這個方法獲得從伺服器傳送的狀態程式碼並顯示出來。

為了測試這一點,在App/Http/Controllers/UserController.php檔案中用下面的程式碼替換之前的巨集程式碼:

function macro()
{
$response = Http::reqres()->get('/users?page=2');
return $response->status();
}

這裡,狀態程式碼200意味著請求成功。

成功解碼響應

成功解碼響應

如何測試JSON APIs

Laravel有幾個輔助函式來測試JSON APIs和它們的響應。這些輔助函式包括json, getJson, postJson, putJson, patchJson, deleteJson, 等等。

為了更好地理解測試,為 GET 使用者的路由建立一個測試場景。當你啟動Laravel應用程式時, Example Test已經被建立。在test/Feature/ExampleTest.php檔案中, 用以下內容替換現有程式碼:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function test_example()
{
$response = $this->getJson('/users');
$response->assertStatus(200);
}
}
<?php namespace Tests\Feature; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; class ExampleTest extends TestCase { /** * A basic test example. * * @return void */ public function test_example() { $response = $this->getJson('/users'); $response->assertStatus(200); } }
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function test_example()
{
$response = $this->getJson('/users');
$response->assertStatus(200);
}
}

新增的程式碼在使用者的路線上獲取JSON資料,並檢查狀態程式碼是否為200。

一旦你新增了測試程式碼,在你的終端執行以下命令來執行測試:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
./vendor/bin/phpunit
./vendor/bin/phpunit
./vendor/bin/phpunit

一旦測試完成,你會看到它執行了兩個測試,都是成功的。

測試JSON APIs

測試JSON APIs

同樣地,你可以檢查不同型別的請求,並利用其他輔助方法進行更復雜的測試。

如何處理事件

Laravel在處理HTTP請求時提供了三個事件。

  • RequestSending, 這是在請求被髮送之前。
  • ResponseReceived, 這是當收到一個響應。
  • ConnectionFailed, 這是在沒有收到響應的時候。

所有這三個事件都包括$ request 屬性,用來檢查 Illuminate\Http\Client\Request 例項,而 ResponseReceived 有一個額外的 $response property。這些對於在事件後執行行動特別有用。例如,你可能想在得到一個成功的響應後傳送電子郵件。

要建立一個事件和監聽器,請瀏覽app/Providers/EventServiceProvider.php檔案,用以下程式碼替換listen陣列。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
'Illuminate\Http\Client\Events\ResponseReceived' => [
'App\Listeners\LogResponseReceived',
],
];
protected $listen = [ Registered::class => [ SendEmailVerificationNotification::class, ], 'Illuminate\Http\Client\Events\ResponseReceived' => [ 'App\Listeners\LogResponseReceived', ], ];
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
'Illuminate\Http\Client\Events\ResponseReceived' => [
'App\Listeners\LogResponseReceived',
],
];

然後在你的終端執行以下命令:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
php artisan event:generate
php artisan event:generate
php artisan event:generate

上述命令將建立app/Listeners/LogResponseReceived.php監聽器。用下面的程式碼替換該檔案的程式碼:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<?php
namespace App\Listeners;
use Illuminate\Http\Client\Events\ResponseReceived;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;
class LogResponseReceived
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct(Request $request, Response $response)
{
Log::channel('stderr')->info($response->status());
}
/**
* Handle the event.
*
* @param \Illuminate\Http\Client\Events\ResponseReceived $event
* @return void
*/
public function handle(ResponseReceived $event)
{
}
}
<?php namespace App\Listeners; use Illuminate\Http\Client\Events\ResponseReceived; use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Support\Facades\Log; class LogResponseReceived { /** * Create the event listener. * * @return void */ public function __construct(Request $request, Response $response) { Log::channel('stderr')->info($response->status()); } /** * Handle the event. * * @param \Illuminate\Http\Client\Events\ResponseReceived $event * @return void */ public function handle(ResponseReceived $event) { } }
<?php
namespace App\Listeners;
use Illuminate\Http\Client\Events\ResponseReceived;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;
class LogResponseReceived
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct(Request $request, Response $response)
{
Log::channel('stderr')->info($response->status());
}
/**
* Handle the event.
*
* @param  \Illuminate\Http\Client\Events\ResponseReceived  $event
* @return void
*/
public function handle(ResponseReceived $event)
{
}
}

狀態程式碼的資訊日誌被輸出到終端。

顯示狀態程式碼的終端日誌

顯示狀態程式碼的終端日誌

小結

無論一個網站或網路應用是由一個組織或獨立開發者製作的,API都是其成功的關鍵。然而,使用它們可能是困難的。

許多框架都承諾簡化這一過程, 但Laravel因其專注於簡單性和易用性而脫穎而出. 他們內建的客戶端支援簡單的API呼叫, 併發的API呼叫, API Macros, 基於JSON的API的輔助方法, 以及更多。

評論留言