Laravel 7.xの新しいHTTP Client!実例

こんにちは。フリーランス・コンサルタント&エンジニアの 九保すこひ です。

さてさて、前回記事 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というサイトを使うことにします。

このサイトは、GETPOSTPUTPATCHDELETEなどのメソッドでアクセスできる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になります。

なお、$responseArrayAccess 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テーブルに登録されているユーザーのemailpasswordでアクセスが出来るようになります。

ダイジェスト認証

$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-Exampletestになっているかどうかをチェックする場合です。

$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をご覧ください。

開発のご依頼お待ちしております
開発のご依頼はこちらから: お問い合わせ
どうぞよろしくお願いいたします! by 九保すこひ

おわりに

ということで、今回はLaravel 7.xの新しいHTTP Clientをご紹介しました。

感想としては、確かにGuzzleよりシンプルで使いやすくて好感が持てました。おそらく個人的にも今後LaravelでHTTPアクセスをする場合は今回の機能を使うと思います。

ぜひ皆さんも試してみてくださいね。

ではでは〜!

このエントリーをはてなブックマークに追加       follow us in feedly