はじめに
この記事はプログラミング初学者による備忘録用の記事であり、また、少しでも他の初学者のお役に立てればと思い書いています。
今回は、APIを扱う練習としてlaravelをベースにGuzzleを使い、NEWS APIからニュースを取得してみました。
間違いなどがございましたら、ご指摘のほどよろしくお願い致します。
事前準備
その1:
NEWS APIにて,APIKeyを取得して下さい。
下記画像の通り、各項目を入力後Submitを押すと取得できます。
composer require guzzlehttp/guzzle
手順
- 取得したAPIkeyを.envファイルに環境変数として設定
- NEWS API用のconfigファイルを作成
- データを取得し表示する為のルーティングを作成
- ルーティングで設定したコントローラーとメソッドを作成
- bladeに連想配列として値を渡し取得したデータを表示
1.取得したAPIKeyを.envファイルに環境変数として設定
NEWS_API_KEY=取得したAPIKeyを記述
NEWS_API_URL='https://newsapi.org/v2/'
2.API用のconfigファイルを作成
<?php
return [
'news_api_url' => env('NEWS_API_URL', null),
'news_api_key' => env('NEWS_API_KEY', null),
];
解説
コントローラーのメソッド内でAPIのurlを設定する時に、config('newsapi.news_api_url')
のように記述して使用します。'news_api_key'
も同様です。
3.データを取得し表示する為にルーティングを作成
<?php
Route::get('/api', 'ApiController@index');
4.ルーティングで設定したコントローラーとメソッドを作成
<?php
namespace App\Http\Controllers;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7;
class ApiController extends Controller
{
public function index()
{
try {
$url = config('newsapi.news_api_url') . "top-headlines?country=us&category=business&apiKey=" . config('newsapi.news_api_key');
$method = "GET";
$count = 15;
$client = new Client();
$response = $client->request($method, $url);
$results = $response->getBody();
$articles = json_decode($results, true);
$news = [];
for ($id = 0; $id < $count; $id++) {
array_push($news, [
'name' => $articles['articles'][$id]['title'],
'url' => $articles['articles'][$id]['url'],
'thumbnail' => $articles['articles'][$id]['urlToImage'],
]);
}
} catch (RequestException $e) {
echo Psr7\Message::toString($e->getRequest());
if ($e->hasResponse()) {
echo Psr7\Message::toString($e->getResponse());
}
}
return view('index', compact('news'));
}
}
解説1
use GuzzleHttp\Psr7;
use GuzzleHttp\Exception\RequestException;
try{
//略
}catch (RequestException $e) {
echo Psr7\Message::toString($e->getRequest());
if ($e->hasResponse()) {
echo Psr7\Message::toString($e->getResponse());
}
try catchを使い、リクエストの転送中にスローされる可能性のあるすべての例外をキャッチするようにしています。下記の説明文はGuzzle公式ドキュメントを翻訳して載せています。
ネットワークエラー(接続タイムアウト、DNSエラーなど)が発生した場合、GuzzleHttp\RequestExceptionがスローされます。この例外は、GuzzleHttpException\TransferExceptionを継承しています。この例外をキャッチすると、リクエストの転送中にスローされる可能性のあるすべての例外がキャッチされます。
解説2
$url = config('newsapi.news_api_url') . "top-headlines?country=us&category=business&apiKey=" . config('newsapi.news_api_key');
$method = "GET";
$count = 15;
$url
と$method
は、後ほど$response = $client->request($method, $url);
のように、リクエストを送る際にメソッドとurlとして使用するので設定しておきます。
今回は、$url
を日本のビジネスというカテゴリのヘッドラインニュースを取得するように設定しています。また、先ほど設定したconfigファイルのkey('news_api_url'と'news_api_key'
)も使用します。
urlの設定方法は、下記の画像のようにNEWS APIの公式サイトに書かれているurlを参考にしています。
$method
はNEWS APIを利用してデータを取得する為にGETメソッド
を使用します。
$count
は表示件数を15としたい為、設定しています。
解説3
$client = new Client();
$response = $client->request($method, $url);
今回は、コードを簡略化して書きたいと思ったので、Guzzle7が提供しているGuzzleHttp\Psr7\Uriクラス
を使用した、インターフェースの実装を試みました。
$response = $client->request('GET', 'http://httpbin.org/get?q=foo');
上記コードの説明
The request URI is represented by a Psr\Http\Message\UriInterface object. Guzzle provides an implementation of this interface using the GuzzleHttp\Psr7\Uri class.
When creating a request, you can provide the URI as a string or an instance of Psr\Http\Message\UriInterface.
解説4
$results = $response->getBody();
GETリクエストのレスポンスのボディをgetBody()メソッドで取得しています。
下記リンク先のコードを参考に設定しました。
$body = $response->getBody();
echo $body;
// Cast to a string: { ... }
解説5
$articles = json_decode($results, true);
NEWS APIからレスポンスとして渡ってくるデータはJSON形式なので、json_decode()メソッド
を使うことでJSONを連想配列にしています。
解説6
$news = [];
for ($id = 0; $id < $count; $id++) {
array_push($news, [
'name' => $articles['articles'][$id]['title'],
'url' => $articles['articles'][$id]['url'],
'thumbnail' => $articles['articles'][$id]['urlToImage'],
]);
}
先ほど、json_decode()メソッド
を使いJSON形式のデータを連想配列に変換したと思います。
dd($articles);
で中身を見てみると下記のように多次元連想配列となっています。
従って、array_push()メソッド
で使いたいkey(データ)を配列に追加するようにします。
流れとしては、$news = [];
で空の配列を作り、繰り返し処理で先ほど作成した$count変数を使い、表示件数(繰り返される回数)を指定、そしてarray_push()メソッド
を使い、対象となる配列を第一引数に、追加する連想配列を第二引数で作成することで空の配列である$news変数にデータが連想配列として格納されます。
5.bladeに連想配列として値を渡し取得したデータを表示
前提として、コントローラーのメソッド内でreturn view('index', compact('news'));
を記述しデータ(連想配列)をbladeに渡します。
そして、下記のように渡ってきた連想配列($news)をforeach文で展開して表示します。
<body>
<div class="container ">
@foreach($news as $data)
<div class="card-body pt-0 pb-2">
<h3 class="h5 card-title">
<a href="{{$data['url']}}">{{$data['name']}}</a>
</h3>
<div class="card-text">
<img src="{{$data['thumbnail']}}">
</div>
</div>
@endforeach
</div>
結果
レイアウトは整えていませんが、下記のように表示できれば成功です。
おわりに
ひとまずエラーなくデータを取得することができたので、次回はこのAPIを活用してニュースアプリを作成してみたいと思います。
最後までお読み頂きありがとうございました。