Laravel開発、Jsonデータ処理を理解してAPIを扱う【2】実際にWebAPIをアプリに組み込む
前回の記事でWebAPIを利用したデータの保存までの流れを学習しました。
今回は、前回の内容を使って、実際に作成中のアプリにWebAPIによる処理を追加してISBNコードによる本情報の追加を実装します。
今回の目的
WebAPIを実際に開発しているアプリで使用し、ISBNコードによる情報登録をする
なぜやるか
- WebAPIを利用した開発をできるようにしたい
- 毎回手動登録のみの状況からユーザーにとってより楽な方法を追加することで、利便性を高めたい
やりたいこと
- 前回記事で作成したWebAPIコードを実際のアプリで組み込む
- 現在のステータスを表示して、ユーザーに状況を伝える
- 登録完了時に登録内容を表示させる
やったこと
- WebAPIを組み込んで使えるようにする
- 入力コードに問題があった時にエラーメッセージを返す
- ビュー画面にメッセージを出力し、ユーザーに状況を伝える
- 登録結果を表示し、ユーザーが登録内容を確認できる
実施内容
WebAPI処理を組み込む
名前を決定する
まず実際に実装するにあたってのルーティングやファイル名を決定します。
下記の設定で実装することにしました。
ISBNコード入力フォームアドレス:~/book/isbn
ファイル名:isbn.blade.php
アクション:getIsbn、postIsbn
この他に、ルート設定・メニューバーにフォームリンク追加・ぱんくずリスト追加等々を実施する必要があります。
実装する
前回の記事で作成したWebAPI処理を反映させていきます。
初めの目標は、WebAPIアクセスして結果をビュー画面上に表示するところから。
コントローラにアクションを追加し、API処理をいれます。
# ~/app/Http/Controllers/BookController.php
ほぼそのまま前回作成したもののコピーです。
まずブラウザ上に結果を返すことを目的としているので、保存処理はコメントあうとしています。
次に、DBに保存するカラムが必要なので、カラム設定を追加します。
# ~/database/migrations/xxxx_create_bookdata_table.php
こちらも前回同様、同じカラムの追加です。既に"title"カラムがあり重複する為、ISBNレコード一覧に書き込みました。
他にISBNコード入力フォーム等も準備し、一端動作チェックしてみましたが、エラー表示となりました。
SQLSTATE[HY000]: General error: 1364 Field 'title' doesn't have a default value (SQL: insert into `bookdata` (`isbn`, `updated_at`, `created_at`) values (9784801907607, 2019-04-07 03:21:31, 2019-04-07 03:21:31))
これは、フォームに誤りがありました。
# ~/resource/views/book/isbn.blade.php
ユーザーによる新規登録フォームをベースに作成したISBNコード入力フォームです。
フォームアクションの修正ができていませんでした…。
アクションを修正してリトライ。
JSONデータを表示させることができました。
# ISBN登録ビュー
DBに保存する
表示確認ができたので、あとはDBに保存すれば本アプリで情報を追加出来るようになります。
先程のコメントアウトしていた保存処理を有効化するだけです。
しかし、保存できませんでした。
データ型を知る
原因を探る内に気づいたのですが、ISBNコードのデータ型設定をinteger形式にしていました。
前回のテスト環境ではstring形式にしていました。
原因調査の為、まず動作していた時と状況を合わせます。
…DB保存できるようになりました。
登録完了はしたのですが、ビュー画面には登録完了メッセージも登録内容も表示されません、まだ作成していないので当然といわれればそうなのですが。
こちらは、後々作成することとします。まずはDBに登録完了。
※ここは今回の実装が終わって後から調べました。
先程のISBNコードがIntegerで保存出来なかった内容について。
Integerに13桁という整数が許容されているかを確認する必要があると思い、調べ見ました。こちらを参考にさせて頂きました、ありがとうございます。
そもそも今回DBはMySQLを利用しており、MySQLで扱えるInterger範囲を確認してみると、13桁は許容していませんでした。
どおりで、登録できなかったわけだ…。
現在の使用はテキスト形式で13文字を保存する形となっています。後でより大きな整数が使用できる数値形式に変更したいと思います。
※ここまで実装後の数値形式調査について。
あらゆるパターンに対応する
今回使用しているWebAPIである"openDB"は13桁のISBNコードに対応しています。
しかし、必ずしも正しい値が入力されるとは限りませんので、様々な状況を想定して問題があればエラーメッセージとして返す処理をいれていきます。
ISBNコード桁数をチェックする
ISBNコードは13桁の数字のみ扱うので、値が正常であるか確認します。
# ~/app/Http/Controllers/BookController.php
桁数が合わない時点で処理を続ける必要はなくなるので、エラーメッセージを追加して、強制的にビュー画面に戻るようにしました。
フォーム入力を数字のみにする
inputタグのタイプをテキストで作成していたので、type="number"にすることでフォーム上で数字のみ受け付けるように設定変更を実施。
# ~/resource/views/book/isbn.blade.php
これでフォームに入力する時点で数値以外は入力できなくなります。
JSONデータが受け取れなかった時の処理
入力コードが正しかったとしてもJSONデータがそもそも存在しない場合があります。
現状のコードではエラー表示となってしまう為、データがなかった場合の処理を追加します。
# ~/app/Http/Controllers/BookController.php
受け取ったJSONデータがない場合はエラーメッセージを返すようにしました。
データ登録処理を見直す
※見直しておきながら最後に問題点に気づいた為、さらに変更しました。修正点は後述しています。
コントローラ処理についても、見直しをかけました。
# ~/app/Http/Controllers/BookController.php
"firstOrNew"によって登録済みのレコードがある場合は、対象レコードを呼び出す形にしました。これによって同じ内容が重複されて保存されることを防いでいます。
重複している場合は、データ更新せずにエラーメッセージを出して終了しています。上書きすると後から修正していたデータが初期化されてしまう為です。
ISBN表示ビューを修正する
ユーザーに対して処理状況を表示して伝える
今までの処理の中で何らかの問題が発生した場合にエラーメッセージとして$msgにテキストを代入しビューで画面させるようにしていました。
しかし、ビュー側にこのテキストを表示させる設定がなかった為、画面上には何も表示されていませんでした。
そこで、処理結果を表示させる機能を追加しました。
表示レイアウトはパンくずリストに似せて作成しました。
全表示パターンで処理状況を出力する
postIsbnアクション上で$msgを追加していたのですが、初めのISBNコード入力画面表示の時のみ$msg処理がはいっていなかったので、こちらも対応させることで、常に何かしらの$msgテキストが存在する状態となるように変更しました。
# ~/app/Http/Controllers/BookController.php
# ビューでメッセージ表示を確認
これで現状のステータス表示ができるようになり、何をすべきか?何が問題か?がユーザーに見えて分かるようになりました。
ISBNコードによる登録結果を出力する
登録されるのみで具体的な結果が表示されない
現状の内容では"データを新規作成しました"と画面には表示されますが、実際にどういう内容が追加されたか?は画面上に表示されない状態です。
登録完了時に登録情報を表示することで、ユーザーが視覚的に確認することができます。
そこで登録完了時に内容を表示させる処理を追加しました。
表示形式を考える
現在作成済みのビューとして「新規登録・一覧表示・詳細表示」等のページが既にあります。これらを流用するか、新たに専用のビューを作成するか検討しました。
詳細表示画面に文字通り詳細情報が出力されるので、今回は詳細表示画面と同様の出力方法で登録完了画面に表示させることにしました。
コンポーネント化して共通表示化する
同じ出力にするのであれば、対象コードをコンポーネント化してやれば簡単に作成できそうです。
というわkで、詳細表示画面であるshowページの一部をコンポーネントに変更しました。
# ~/resource/views/book/show.blade.php
@include()として呼び出し形式に変更。
呼び出される側の新コンポーネントファイルを作成します。
# ~/resource/views/components/book_detail.blade.php
showページを確認し型崩れしていないことを確認しました。
後はISBN登録ページの下部に同じコンポーネントを利用して登録完了時にデータを表示できるようにします。
# ~/resource/views/book/isbn.blade.php
これで実際に登録をしてみます。
これで登録ボタンを押してISBNデータがあればDB登録され、登録結果が表示されるようになりました。
ここまでで、ISBNコード指定→登録処理→登録結果表示ができるようになりました。
取得したDB情報を全て反映する
後はコンポーネントの表示が古いままで「仮置」といった表示があるので、DBに保存している情報を反映できるように変更します。
コンポーネントを修正することで、詳細ページと新規登録時の表示共に反映することができます。
# ~/resource/views/components/book_detail.blade.php
ISBNから取得する情報に画像情報もあるので、画像の表示処理も変更しました。
# ~/resource/views/components/book_detail.blade.php
ユーザ登録画像を最優先、ISBN取得による画像があれば表示、なければ画像なしの処理としました。
コンポーネントを直したので、詳細ページでまず表示を確認。
DB保存情報が正しく反映されました。
ISBNによる新規登録時の表示も確認します。
こちらも問題なく表示できました。
書籍詳細を反映させる
先程の表示結果にもありますが、画面下部に書籍詳細という文字通り詳細情報を記載する欄を設けています。
JSONデータ上に詳細情報も実はありました。今までのJSONデータは、その一部のみを取得して実装していたのですが、せっかく詳細表示するビューがあるので、対象の情報を追加取得できるようにしました。
ISBNレコードから詳細情報があるデータを個別に選択して取り出します。
"BiographicalNote"という項目に詳細が書いていたので、これを取り出して反映させることとしました。
しかし、必ずこのキーに対する情報が有るわけではありません。
データがなかった場合エラー画面が出力されていました。
そこで、empty()でデータが存在するかを確認して、ある場合のみ取り出す方法としました。
以上でISBNコードを利用した情報登録については完了です。
データ登録処理の問題に気づく
ここまで実施して、最後にプルリクエストを書いているときに一つ気がつきました。
「JSONデータ取得後に登録済みISBNであれば登録しない処理を書いている。」
よくよく考えてみると、API通信する前に登録しない情報は排除すべきだと…。
WebAPIは接続数に対して制限や料金がかかる物もあり、そもそも無駄な通信はさけるべきです。
ということで、API通信前に登録済みか確認する処理を追加することにしました。
これでこの後の処理も変わります。
"\App\Bookdata::firstOrNew"として、レコードがない場合は新規登録としていましたが、レコードのあるパターンは上記で処理済みの為、新規登録処理のみに変更できます。
新規レコードのみの処理となるので、レコードを新規作成し、データを追加する形に変更しました。
処理が整理できてみやすくなり、余計な通信も遮断できました。
細々した修正点はまだいろいろとありそうですが、これでISBN登録処理については一端完了とします。