Laravel 楽天ブックス書籍検索APIを利用して本のタイトルを一覧表示する 

簡単な外部APIをLaravelから実行する方法です。GuzzleというLaravelのHTTPクライアントライブラリを使っています。今回は楽天ブックス書籍検索APIを利用します。APIからJSONで返ってきた書籍のタイトルをビューにリスト表示するだけのデモです。

###楽天ブックス書籍検索APIとは
楽天ブックスで販売されている書籍の情報を取得することが可能なAPIです。 

###Guzzleとは
簡単にHTTPリクエストを行えるPHPのHTTPクライアントライブラリです。

#手順
1. 楽天ブックス書籍検索APIに登録する
2. Guzzleパッケージをインストール
3. GETメソッドでAPIのURLに接続してJSONを返してくるコードを書く
4. 配列の値をビューに返す

##1. 楽天ブックス書籍検索APIに登録する
APIを利用するためにアプリケーションIDが必要となるのでまず取得します。楽天Webサービスのページ(https://webservice.rakuten.co.jp/)
にアクセスして取得してください。メニューからアプリ登録という作業が必要になります。特に作るアプリがなくても、仮のURLを登録しておけばAPI自体は使えます。

##2. Guzzleパッケージをインストール
公式ドキュメント(https://docs.guzzlephp.org/en/stable/index.html)
の通りにcomposerを使ってインストールします。

```
composer require guzzlehttp/guzzle
```

##3. GETメソッドでAPIのURLに接続してJSONを返してくるコードを書く

###3.1 Laravelのルート定義
事前準備としてコードを書く前にControllerを作成しておきます。作成した`ApiController` のメソッドにコードを書くので、以下のようにルート定義をします。

```/routes/web.php
use App\Http\Controllers\ApiController;

//ApiControllerのgetApi()を呼び出す
Route::get('api', [ApiController::class, 'getApi']);
```

###3.2 Controllerのメソッドとしてコードを書く

```/app/Http/Controllers/ApiController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

// GuzzleというPHPのHTTPクライアントライブラリを使う
use GuzzleHttp\Client;

class ApiController extends Controller
{
    public function getApi()
    {
        	//外部APIのURLを指定する(楽天ブックス書籍検索API)
        	$url = 'https://app.rakuten.co.jp/services/api/BooksBook/Search/20170404';

        	/*
        	option配列をrequestとして送ることで、配列の中身のクエリ文字列をPHPのhttp_build_query関数を
        	使用してフォーマット。
        	*/

        	$option = [
        		'query' => [
        			/* クエリ文字列をセットする
                    */
                    // レスポンスをJSON形式で受け取る
        			'format' => 'json',

                    // 書籍タイトル　（例）「地球」をタイトルに含むものを検索する場合
        			'title' => '地球',

                    // 楽天ブックスにおけるジャンルを特定するためのID
        			'booksGenreId' => '001004008',

                    // 手順1.で取得したアプリケーションID
        			'applicationId' => '1014145894144821916'
                ]
        	];

            // URIを指定してクライアントを生成
        	$config = ['base_uri' => 'http://localhost/laravelapp/public/api/'];
        	$client = new Client($config);

        	$response = $client->request('GET', $url, $option);

            //返されるJSONデータのマルチバイト文字（日本語など）はUnicodeポイント表記で読めない。
            //JSON_UNESCAPED_UNICODEを指定して日本語をそのまま表示。
        	$list = json_encode(json_decode($response->getBody()->getContents(), true), JSON_UNESCAPED_UNICODE);

        	// JSONを連想配列化
        	$items = json_decode($list, true)["Items"];

        	// api.blade.phpというビューに第二引数の値をビュー側にitemsという名前の連想配列として渡す
        	return view('api' , compact('items'));

    }


}

?>

```

`Client`を`new`で作成する時に、リクエスト送信元のURL( `web.php` で定義したルートのURL）を指定します。

`request()`については、HTTPメソッドのGETでURLにリクエストを送ります。`$option`は先述したリクエストクエリの配列として定義したものになります。

`$response->getBody()->getContents()`が外部APIのレスポンスボディの内容。


楽天ブックス書籍検索APIは、以下のような形式でレスポンスを返します。なので、PHPの`$items`には、その`"Items"`キーに対応するバリューの部分が連想配列として入っていることになります。

```
{
  "GenreInformation": [],
  "Items": [
    {
      "Item": {
      "author": "多和田 葉子",
      "publisherName": "講談社",
      "title": "地球にちりばめられて",
      }
    },
    {
      "Item": {
       ... 
      }   
    },
    ...
  ]

}
```

`compact()`は指定した名前の連想配列  `$items`  を要素にもつ配列を返します。
        	 `compact('items')` なら　`[ $items ]` を返すイメージ。 

`$items` の中には、`{ "Item": {"author": "多和田 葉子", ...} }, { "Item": {"author":xxx, ...} }` というように`"Item"`がいくつも入っています。
`$items` にAPIが返す書籍の数だけ `"Item"` が入っていることになります。

###4.配列の値をビューに返す
次に、`ApiController` から ビューに`$items` を渡し、データを表示します。

```/resources/views/api.blade.php
@extends('components.common.layout')

@section('index')

	@foreach ($items as $item )
		{{ $item["Item"]["title"] }}<br>
	@endforeach

@endsection
```

ビューでは各 `Item` の `title` を `@foreach...@endforeach` の中で繰り返し取得します。
`@extends` ディレクティブで親のビューを指定します。

```/resources/views/components/common/layout.blade.php
@yield('index')
```

親ビューの `@yield` ディレクティブは、子ビューの `@section` ディレクティブにコンテンツを挿入します。ここでは `{{ }}` 内の変数にコントローラから受け取った書籍のタイトルを表示しています。

親ビューの `artisan` コマンドでの作成方法は以下を参考にしました。
[今更ながらLaravel8.xのComponentを使う](https://qiita.com/silver40/items/91340763b21da916577e)
コマンドは以下のようになります。

```
php artisan make:component common/layout
```

#結果
楽天ブックス書籍検索APIから以下のように本のタイトルを取得できました。

```
縄文のコトタマが地球を救う
地球星人
地球にちりばめられて
小説　地球万華鏡
われら滅亡地球学クラブ
UFOエネルギーとNEOチルドレンと高次元存在が教える地球では誰も知らないこと
......
```

#感想
Guzzleを使ったのはこれが初でしたが、特に困ることなく便利でした。むしろAPIのJSONの扱いに手間取りました。

最後ビューにデータを渡す時に、PHPの `compact()` を使うのがミソだったと思います。コントローラ側と同じ配列の変数をビュー側に渡せばいいので。