九保すこひ@フリーランスエンジニア|累計300万PVのブログ運営中
さてさて、前回記事 Laravel 7.xの新ルート機能 では、Laravel
の新しいルート機能をご紹介しました。
そして、今回もこの流れで便利な「ある機能」をご紹介したいと思います。
その機能とは・・・
HTTPクライアント機能
です。
つまり、Laravel
(PHP)からインターネットのウェブサイトにHTTPでアクセスする機能ですね。
ただ、もしかすると
「PHP で HTTPリクエストするならGuzzleがあるじゃん・・・」
と思われたかもしれません。
先に言っておきますと、今回の新しいHTTP機能は内部的に「Guzzle」を使っています。でも、どうやらよく使う部分はLaravel
側で簡単に使えるようにしようということになったようです。(つまりラッパークラスですね)
そこで!
今回はLaravel 7.x
の新機能のHTTP Client
の使い方を実例でご紹介したいと思います。
ぜひ皆さんのお役に立てると嬉しいです😊✨
開発環境: Laravel 7.x
目次
パッケージのインストール
今回必要となるのはGuzzle
ですが、すでにインストールされているはずです。
もしインストールされていないようでしたら以下のコマンドを実行してください。
composer require guzzlehttp/guzzle:^6.3
使い方を紹介する前に
今回、HTTP Client
でアクセス・テストをするわけですが、いちいち自前でアクセスするページを作るのはめんどうですので、JSONPlaceholderというサイトを使うことにします。
このサイトは、GET
やPOST
、PUT
、PATCH
、DELETE
などのメソッドでアクセスできるURL
を用意してくれていて、テストにはとても重宝します。(無料です)
また、HTTPステータス・コードが関連するテストには、httpstat.usを使います。
基本的な使い方
では、ここから実際にコードを紹介していきますが、ネームスペースは省略しますので、先に以下のコードをコントローラーやルートに追加しておいてください。
use \Illuminate\Support\Facades\Http;
パラメータなしで送信する場合
まずはパラメータなしで送信する場合です。
// GET $response = Http::get('https://jsonplaceholder.typicode.com/posts/1'); // POST $response = Http::post('https://jsonplaceholder.typicode.com/posts'); // PUT $response = Http::put('https://jsonplaceholder.typicode.com/posts/1'); // PATCH $response = Http::patch('https://jsonplaceholder.typicode.com/posts/1'); // DELETE $response = Http::delete('https://jsonplaceholder.typicode.com/posts/1');
※レスポンスの処理についてはレスポンスを処理するをご覧ください。
パラメータをつける場合
パラメータをつけて送信する場合は、第2引数に配列で指定します。
$response = Http::post($url, [ 'key_1' => 'value - 1', 'key_2' => 'value - 2', 'key_3' => 'value - 3', ]);
※もちろん、POST
以外でもこの形でパラメータ送信ができます。
ただし、パラメータの送信は初期状態ではapplication/json
として送信されることになります。そのため、実際のフォーム送信のようにする場合はasForm()
と一緒に使ってください。
$response = Http::asForm()->post($url, [ 'key_1' => 'value - 1', 'key_2' => 'value - 2', 'key_3' => 'value - 3', ]);
レスポンスを処理する
レスポンスBodyを取得する
レスポンスBody(ブラウザで表示される部分)を取得するには以下のようにします。
echo $response->body();
JSONをパース(配列、オブジェクト化)する
レスポンスBodyがJSON
形式の場合、以下のようにすることで配列やオブジェクトとしてデータ取得することができます。
$data = $response->json();
※もしBody
のデータがJSON
ではない場合はnull
になります。
なお、$response
はArrayAccess interface
に対応しているので、json()
を使わなくとも以下のように直接データを取得することもできます。
echo $response['title'];
ヘッダーを取得する
全てのヘッダーを取得する
一気に全てのヘッダーを取得するには以下のようにします。
$headers = $response->headers();
特定のヘッダーだけ取得する
特定のヘッダーだけ取得する場合は以下のようにします。
$content_type = $response->header('Content-Type');
HTTPステータスコードを取得する
$status_code = $response->status(); // 200など
アクセスしたURLに関する情報を取得する
例えば、scheme
や、host
など以下のような情報を取得する場合です。
$url_info = $response->effectiveUri();
クッキーを取得する
クッキーを取得する場合は少しだけ注意が必要です。
というのも、cookies()
で取得できるのはGuzzle
が提供するCookieJar
というクラスのインスタンスなので以下のようにしないといけないからです。
$response = Http::get($url); $cookies = $response->cookies(); // GuzzleHttp\Cookie\CookieJar echo $cookies->getCookieByName('key')->getValue();
※Laravel
のコードを見る限りcookies()
の説明書きに@return array
と書いてありましたので、もしかするとちょっとした表記ミスの可能性もあります。(2020.03.04現在)
PSR-7形式のレスポンスに変換する
$psr_response = $response->toPsrResponse();
例外処理をする
もしステータス・コードが400番台、もしくは500番台のときに例外処理実行することができるのがthrow()
です。
使い方は以下のようになります。
$url = 'https://httpstat.us/404'; $response = Http::get($url); $response->throw();
この場合、ステータス・コードは404
なので以下のような表示になります。
レスポンスの結果を判別する
HTTPでアクセスした結果がどのようなものだったかをtrue
/ false
で返してくれるメソッドの一覧です。
全てHTTPステータス・コードで判別されます。
ステータス・コードが200
if($response->ok()) { // ステータス・コード: 200 }
ステータス・コードが 200番台
if($response->successful()) { // ステータス・コード: 200〜299 }
ステータス・コードが 300番台
if($response->redirect()) { // ステータス・コード: 300〜399 }
ステータス・コードが 400番台
if($response->clientError()) { // ステータス・コード: 400〜499 }
ステータス・コードが 500番台
if($response->serverError()) { // ステータス・コード: 500〜599 }
ファイルをアップロードする
ファイルをアップロードする場合はattach()
を使います。
$name = 'image'; $content = file_get_contents('images/test.jpg'); $filename = 'image.jpg'; // 省略可 $url = 'http://example.test/file_upload'; $response = Http::attach($name, $content, $filename)->post($url);
なお、ファイルと一緒に通常のパラメータを送信する場合は、以下のように指定することはできません。
// ⚠️【注意】これは間違った例です! $response = Http::attach($name, $content, $filename) ->post($url, [ 'key' => 'value' // 通常のパラメータ指定方法はエラーになる ]);
その場合は、ファイルの指定と同じように繰り返しattach()
を使いましょう。
$response = Http::attach($name, $content, $filename) ->attach('key', 'value') // 通常のパラメータ ->post($url);
ヘッダーを指定する
ヘッダーを指定するにはwithHeaders()
を使います。
$response = Http::withHeaders([ 'X-Program' => 'Work', 'X-Piano' => 'Life', 'X-Beer' => 'Energy' ])->get($url);
認証情報を追加する
ベーシック認証
$username = 'taro@example.com'; $password = 'secret'; $response = Http::withBasicAuth($username, $password)->get($url);
なお、Laravel
には簡単にベーシック認証を有効にするミドルウェアがあります。
Route::get('basic_auth', function(){ return 'OK!'; })->middleware('auth.basic');
この場合、users
テーブルに登録されているユーザーのemail
とpassword
でアクセスが出来るようになります。
ダイジェスト認証
$username = 'taro@example.com'; $password = 'secret'; $response = Http::withDigestAuth($username, $password)->get($url);
Bearerトークン
$token = 'Your-Bearer-Token'; $response = Http::withToken($token)->get($url);
再アクセス
Http Client
にはアクセスが失敗した場合に繰り返しアクセスを試みるretries()
が用意されています。
$times = 3; // アクセスを試みる最大回数 $sleep = 1000; // 待機するミリ秒 $response = Http::retries($times, $sleep)->get($url);
テスト機能
Http Client
には、開発のための便利な機能も用意されています。
もし、まだコードがしっかり固まっていない場面では、この機能で実際にはアクセスせずに確認できますので、アクセス先に過度の負荷をかけることもなく、もちろんブロックされることもありません。
基本的な使い方
では、実際の例を見てみましょう。
例えば、your-site.test
にアクセスしたら以下のようなレスポンスが返るようにする場合です。
- レスポンスBody ・・・ テスト文字列
- HTTPステータス・コード ・・・ 200
- ヘッダー ・・・ X-Example: Example Header
$body = 'テスト文字列'; // 配列の場合はJSONが返ります $status = 200; $headers = ['X-Example' => 'Example Header']; Http::fake([ 'your-site.test/*' => Http::response($body, $status, $headers) ]); // テストでHTTPアクセス $response = Http::post('http://your-site.test/test');
なお、fake()
には、複数のサイトを指定することもできますし、*
を使えばアクセスするサイトがリストに存在しない場合のレスポンスを返すことができます。
Http::fake([ 'your-site.test/*' => Http::response($body, $status, $headers), 'your-site2.test/*' => Http::response($body, $status, $headers), '*' => Http::response($body, $status, $headers) // サイトが存在しない場合 ]);
連続したレスポンス
例えば、以下の順番でHTTPアクセスをテストしたい場合を見てみましょう。
- http://your-site.test/test
- http://your-site.test/test2
- http://your-site.test/test3
この場合は以下のようにsequence()
を使って処理します。
Http::fake([ 'your-site.test/*' => Http::sequence() ->push('テスト文字列', 200) ->push(['key' => 'value'], 200) ->pushStatus(404) ->whenEmpty(Http::response()), ]);
そして、もし以下のように3回アクセスした場合レスポンスは指定した順で取得されることになり、もし返すべきレスポンスが無くなってしまった場合はwhenEmpty()
が実行されることになります。
$response_1 = Http::get('http://your-site.test/test'); // テスト文字列 $response_2 = Http::get('http://your-site.test/test2'); // ['key' => 'value'] $response_3 = Http::get('http://your-site.test/test3'); // 404
正しい情報が含まれているかチェックする
Http::fake()
を使ってHTTPアクセスした直後にassertSent()
を使うことで、そのリクエストに正しい情報が含まれているかをチェックすることができます。
例えば、ヘッダーのX-Example
がtest
になっているかどうかをチェックする場合です。
$response = Http::withHeaders(['X-Example' => 'test'])->post('http://your-site.test/test'); Http::assertSent(function ($request) { return $request->hasHeader('X-Example', 'test'); });
また、$request
には以下のような情報も含まれているのでこれらを使って「本当にこのアクセスには必要な情報が入っているか??」をテストすることができます。
- $request->url() ・・・ アクセスしたURL
- $request->method() ・・・ 送信メソッド
- $request[‘***’] ・・・ 送信した値
より詳しいメソッドは、/vendor/laravel/framework/src/Illuminate/Http/Client/Request.php
をご覧ください。
おわりに
ということで、今回はLaravel 7.x
の新しいHTTP Client
をご紹介しました。
感想としては、確かにGuzzle
よりシンプルで使いやすくて好感が持てました。おそらく個人的にも今後Laravel
でHTTPアクセスをする場合は今回の機能を使うと思います。
ぜひ皆さんも試してみてくださいね。
ではでは〜!