3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[laravel]NEWS APIを使いデータを取得してみた

Posted at

はじめに

この記事はプログラミング初学者による備忘録用の記事であり、また、少しでも他の初学者のお役に立てればと思い書いています。

今回は、APIを扱う練習としてlaravelをベースにGuzzleを使い、NEWS APIからニュースを取得してみました。

間違いなどがございましたら、ご指摘のほどよろしくお願い致します。

事前準備

その1:
NEWS APIにて,APIKeyを取得して下さい。
下記画像の通り、各項目を入力後Submitを押すと取得できます。

スクリーンショット 2021-04-05 16.18.31.png
その2:
Guzzleをインストール

composer require guzzlehttp/guzzle

手順

  1. 取得したAPIkeyを.envファイルに環境変数として設定
  2. NEWS API用のconfigファイルを作成
  3. データを取得し表示する為のルーティングを作成
  4. ルーティングで設定したコントローラーとメソッドを作成
  5. bladeに連想配列として値を渡し取得したデータを表示

1.取得したAPIKeyを.envファイルに環境変数として設定

/.env
NEWS_API_KEY=取得したAPIKeyを記述
NEWS_API_URL='https://newsapi.org/v2/'

2.API用のconfigファイルを作成

config/newsapi.php

<?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.データを取得し表示する為にルーティングを作成

routes/web.php
<?php

Route::get('/api', 'ApiController@index');

4.ルーティングで設定したコントローラーとメソッドを作成

ApiController.php
<?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を継承しています。この例外をキャッチすると、リクエストの転送中にスローされる可能性のあるすべての例外がキャッチされます。

参考:Guzzle Docs Quickstart

解説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を参考にしています。
スクリーンショット 2021-04-05 17.16.21(2).png
$methodはNEWS APIを利用してデータを取得する為にGETメソッドを使用します。
$countは表示件数を15としたい為、設定しています。

解説3


$client = new Client();
$response = $client->request($method, $url);

今回は、コードを簡略化して書きたいと思ったので、Guzzle7が提供しているGuzzleHttp\Psr7\Uriクラスを使用した、インターフェースの実装を試みました。

参考:Guzzle7 Request 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: { ... }

参考:Guzzle7 Responses Body

解説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);で中身を見てみると下記のように多次元連想配列となっています。
スクリーンショット 2021-04-05 18.11.57(2).png
従って、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>

結果

レイアウトは整えていませんが、下記のように表示できれば成功です。
スクリーンショット 2021-04-05 18.45.11(2).png

おわりに

ひとまずエラーなくデータを取得することができたので、次回はこのAPIを活用してニュースアプリを作成してみたいと思います。

最後までお読み頂きありがとうございました。

参考文献

phpマニュアル
Guzzle7 公式ドキュメント
Guzzle GitHub
NEWS API

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?