Fippiyのプログラム学習内容アウトプットBlog

日々の学習内容をアウトプットして振り返りを実施する。

Laravel開発、ISBNレコードを複数登録する【2】処理コードを書く

ISBNコードを利用して簡単に書籍情報を登録できるようにしていました。

しかし、1件のみ毎回登録する…といったパターンしか行えない状態なので、まとめて追加できるようにしてみました。

最終目的

ISBNコードを10件まで1フォームから入力して登録できるようにする

今回の目的

新規登録となるISBNコードを選別する。

APIを利用してDBに登録し、結果を表示させる

なぜやるか

  • 仕様に合わないデータは予め対象外とすることでAPI通信を最低限とするため
  • 選別作業を先に行うことで、不要なSQL文の発行を防止するため
  • 将来的に大量のデータを個別処理するにあたってのプロセスとして複数登録処理を作成する

やりたいこと

  • 入力データ全てを評価し、13桁のコードのみを処理する
  • 入力データ内で重複していないかチェックをする
  • DB登録済みでないかをチェックする
  • 全ての処理結果を一覧出力する

やったこと

入力コード処理用の配列を準備する

 

実施内容

 

処理コードを確認する

まずは、今回作成したコード内容を表示します。

複数ページ表示用のコード

# ~/resources/views/book/isbn_some.blade.php

public function getIsbnSome(){
 $msg = 'ISBNコードを入力して下さい。';
 return view('book.isbn_some',['msg'=>$msg]);
}

ISBNコードを複数入力するページを表示させる為、入力ページへ移動させる為のアクションです。こちらはビュー指定のみです。

 

postデータ処理のコード

# ~/resources/views/book/isbn_some.blade.php

public function postIsbnSome(Request $request){

 // フォームデータ取得
 unset($request['_token']); // トークン削除
 $isbns = $request->all(); // isbnコードをフォームから取得
 $count = count($isbns); // 取得件数

 // 処理用配列へ追加
 for ($i = 0; $i < $count; $i++){
  $isbnrecords = array(
   'number' => $i+1,
   'isbn' => $isbns['isbn'.$i],
   'msg' => null,
  );
 }

 // フォームデータ評価
 for ($i = 0; $i < $count; $i++){
  if ($isbnrecords[$i]['msg'] == null){ // メッセージ格納済みは対象外
   if (mb_strlen($isbnrecords[$i]['isbn']) == null){
    data_set($isbnrecords[$i], 'msg', 'ISBNが登録されていません'); // 未登録時はメッセージ格納
   } elseif (mb_strlen($isbnrecords[$i]['isbn']) != 13){
    data_set($isbnrecords[$i], 'msg', '桁数が13桁ではありません。');
    // 13桁でない場合はメッセージ格納
   } else {
    for ($j = $i+1; $j < $count; $j++){
     if ($isbnrecords[$i]['isbn'] == $isbnrecords[$j]['isbn']) {
      data_set($isbnrecords[$j], 'msg', ($i+1)."件目のデータと同じです。");
      // フォームデータ重複チェック
     }
    }
   }
   // DBユニークチェック
   if (Bookdata::where('isbn', $isbnrecords[$i]['isbn'])->first() != null){
    data_set($isbnrecords[$i], 'msg', '既に登録されています。'); // DB存在時はメッセージ格納
   }
  }
 }

 // ISBNコードから本情報を取得
 $isbn_url = 'https://api.openbd.jp/v1/get?isbn='; // API設定
 // 検索該当レコードのみデータ取得を実施
 // foreach ($isbns as $isbn) {
 for ($i = 0; $i < $count; $i++){
  if ($isbnrecords[$i]['msg'] == null){ // メッセージ格納済みは対象外
   $isbn = $isbnrecords[$i]['isbn'];
   $response = file_get_contents($isbn_url.$isbn);
   $result = json_decode($response, true);
   data_set($isbnrecords[$i], 'result', $result); // 結果を格納
 
   // ISBNレコード結果を確認
   // result[0]の情報有り無しで判定
   if($isbnrecords[$i]['result'][0] == null) {
    data_set($isbnrecords[$i], 'msg', '該当するISBNコードは見つかりませんでした。');
    // 未登録時はメッセージ格納
   }
  }
 }

 // msgがnullのままの状態の物のみ登録する
 for ($i = 0; $i < $count; $i++){
  if ($isbnrecords[$i]['msg'] == null){ // メッセージ格納済みは対象外

   // ISBNレコードがあれば追加処理
   $savedata = new Bookdata;

   // summaryData取得
   $getdata = $isbnrecords[$i]['result'][0]["summary"];
   // 要素毎にレコードに追加
   foreach($getdata as $key => $value){
    if(strlen($value) == 0){
     $savedata->$key = null;
    } else {
     $savedata->$key = $value;
    }
   }
   // detail取得
   $detail_datacheck = empty($isbnrecords[$i]['result'][0]["onix"]
    ["DescriptiveDetail"]["Contributor"][0]["BiographicalNote"]);
   if(strlen($detail_datacheck) == true){
    $savedata->detail = null;
   } else {
    $savedata->detail = $isbnrecords[$i]['result'][0]["onix"]
     ["DescriptiveDetail"]["Contributor"][0]["BiographicalNote"];
   }
   // 保存
   $savedata->save();
   data_set($isbnrecords[$i], 'result', $savedata); // 未登録時はメッセージ格納
   // 保存完了メッセージ
   data_set($isbnrecords[$i], 'msg', '登録しました'); // 未登録時はメッセージ格納
  }
 }

 // ビューに出力
 return view('book.isbn_result',['answers' => $isbnrecords]);
}

 

詳しい内容についてはこの先で記載していきます。

 

postデータ処理コードを確認する

フォームからの値を受け取る

まずは、入力値を受け取ります。

public function postIsbnSome(Request $request){

 // フォームデータ取得
 unset($request['_token']); // トークン削除
 $isbns = $request->all(); // isbnコードをフォームから取得
 $count = count($isbns); // 取得件数

この時の変数格納データを確認しました。

# terminal

$isbns

=> [

     "isbn0" => "9784797398892",

     "isbn1" => "9784756918765",

     "isbn2" => "9784844366454",

   ] 

$count

=> 3

 

フォームよりデータを受け取った時の変数内容としては、名前と値のセットが格納されています、件数も正しい値が取得できています。

 

データ処理用配列へ格納する

取得したISBNコードに対してそれぞれ処理を実施していく準備をします。

番号・ISBNコード・処理結果メッセージが格納できるようにしました。

// 処理用配列へ追加
for ($i = 0; $i < $count; $i++){
 $isbnrecords = array(
  'number' => $i+1,
  'isbn' => $isbns['isbn'.$i],
  'msg' => null,
 );
} 

メッセージには処理が完了した段階で、処理結果を入力する形としました、まだ処理前なので現段階では何も入っていません。

本の情報を取得すれば、データとして追加する必要がありますが、全てのコードに対して取得できるとは限らないので、取得時に追加でキーもあわせて追加します。

# terminal

$isbnrecords

=> [

     [

       "number" => 1,

       "isbn" => "9784797398892",

       "msg" => null,

     ],

     [

       "number" => 2,

       "isbn" => "9784756918765",

       "msg" => null,

     ],

     [

       "number" => 3,

       "isbn" => "9784844366454",

       "msg" => null,

     ],

   ]

フォームから取得したISBNに対して番号とメッセージを付加して格納しました。

 

受け取ったデータを確認する

ISBNコード毎にデータの受け取りができたので、まずはISBNの値を確認していきます。

// フォームデータ評価
for ($i = 0; $i < $count; $i++){
 if ($isbnrecords[$i]['msg'] == null){ // メッセージ格納済みは対象外
  ...
 }
}

フォーム評価の冒頭部分です、forで繰り返しを行い、メッセージがnull状態の物に対して処理を実施しています。

処理が完了した段階でメッセージを登録すれば、すべてのメッセージが登録されれば処理が完了する…といった手順で実施すればいいと考えました。

 

そして、メッセージがない場合についてISBNに対して処理を実施します。

if (mb_strlen($isbnrecords[$i]['isbn']) == null){
 data_set($isbnrecords[$i], 'msg', 'ISBNが登録されていません'); // 未登録時はメッセージ格納
} elseif (mb_strlen($isbnrecords[$i]['isbn']) != 13){
 data_set($isbnrecords[$i], 'msg', '桁数が13桁ではありません。');
 // 13桁でない場合はメッセージ格納
} else {
 for ($j = $i+1; $j < $count; $j++){
  if ($isbnrecords[$i]['isbn'] == $isbnrecords[$j]['isbn']) {
   data_set($isbnrecords[$j], 'msg', ($i+1)."件目のデータと同じです。");
   // フォームデータ重複チェック
  }
 }
}
// DBユニークチェック
if (Bookdata::where('isbn', $isbnrecords[$i]['isbn'])->first() != null){
 data_set($isbnrecords[$i], 'msg', '既に登録されています。'); // DB存在時はメッセージ格納
}

未入力時と13桁でない物についてメッセージをかえしています、ISBNは13桁のみ対応としていたので、処理対象外として簡単に処理できるものから除外しています。

 

その次に、フォーム入力データ内で重複がないか確認をしています。

処理中のISBNの次のデータから最後までを照合し、同じISBNがあればメッセージを入力しています。

メッセージ入力済みのISBNは後から処理手番になった時にはメッセージが既に入っているので処理対象外となり同じことをすることはありません。

 

13桁で入力フォームの重複チェックまで終わったISBNは、この段階でDB検索を行い、DBに登録済みかを確認します。登録済みであれば、登録済みであるメッセージが登録されます。

 

実際にデータを登録して確認しました。 

# terminal

$isbnrecords

=> [

     [

       "number" => 1,

       "isbn" => null,

       "msg" => "ISBNが登録されていません",

     ],

     [

       "number" => 2,

       "isbn" => "978475691876",

       "msg" => "桁数が13桁ではありません。",

     ],

     [

       "number" => 3,

       "isbn" => "9784844366454",

       "msg" => "既に登録されています。",

     ],

     [

       "number" => 4,

       "isbn" => "9784797398892",

       "msg" => null,

     ],

     [

       "number" => 5,

       "isbn" => "9784797398892",

       "msg" => "4件目のデータと同じです。",

     ],

   ]

この場合、4件目のみ全てのチェックをクリアしたので、処理結果メッセージはなにも登録されておらず、次の工程にすすみます。

 

ISBNから情報を取得する

事前のISBNチェックが完了したデータを対象にAPIを利用して情報を取得します。

// ISBNコードから本情報を取得
// 検索該当レコードのみデータ取得を実施
for ($i = 0; $i < $count; $i++){
 if ($isbnrecords[$i]['msg'] == null){ // メッセージ格納済みは対象外
  $isbn = $isbnrecords[$i]['isbn'];
  $response = file_get_contents($isbn_url.$isbn);
  $result = json_decode($response, true);
  data_set($isbnrecords[$i], 'result', $result); // 結果を格納
 
  // ISBNレコード結果を確認
  // result[0]の情報有り無しで判定
  if($isbnrecords[$i]['result'][0] == null) {
   data_set($isbnrecords[$i], 'msg', '該当するISBNコードは見つかりませんでした。');
   // 未登録時はメッセージ格納
  }
 }
}

データが取得できた物は、data_set()を利用してresultカラムを追加してデータを格納しています。検索できなかった場合はメッセージに見つからなかった旨のメッセージを登録しています。

API情報の取得自身は単体のISBNでの登録時と特に変わりはありません、格納する場所が複数ISBN用の配列に変わっているくらいでしょうか。

 

取得データをDBへ登録する

取得したデータから必要な情報をDBへ登録します。

// msgがnullのままの状態の物のみ登録する
for ($i = 0; $i < $count; $i++){
 if ($isbnrecords[$i]['msg'] == null){ // メッセージ格納済みは対象外
  // ISBNレコードがあれば追加処理
  $savedata = new Bookdata;
  // summaryData取得
  $getdata = $isbnrecords[$i]['result'][0]["summary"];
  // 要素毎にレコードに追加
  foreach($getdata as $key => $value){
   if(strlen($value) == 0){
    $savedata->$key = null;
   } else {
    $savedata->$key = $value;
   }
  }
  // detail取得
  $detail_datacheck = empty($isbnrecords[$i]['result'][0]["onix"]
   ["DescriptiveDetail"]["Contributor"][0]["BiographicalNote"]);
  if(strlen($detail_datacheck) == true){
   $savedata->detail = null;
  } else {
   $savedata->detail = $isbnrecords[$i]['result'][0]["onix"]
    ["DescriptiveDetail"]["Contributor"][0]["BiographicalNote"];
  }
  // 保存
  $savedata->save();
  data_set($isbnrecords[$i], 'result', $savedata); // 未登録時はメッセージ格納
  // 保存完了メッセージ
  data_set($isbnrecords[$i], 'msg', '登録しました'); // 未登録時はメッセージ格納
 }
}

// ビューに出力
return view('book.isbn_result',['answers' => $isbnrecords]);

こちらについても単体のISBN登録時と処理方法は同じです。

複数ISBN用の配列に対応させています。

登録完了時にメッセージに「登録しました」と追加しています。

f:id:Fippiy:20190517122218p:plain

登録完了イメージ

 

 

$isbnrecordsに格納していた処理結果を使用して最終的に処理結果を専用ビューで表示させて完了です。 

 

以上で複数ISBNコード登録完了…としたかったのですが、ここまで実装してからいろいろ修正したいことが発生しましたので、そちらを次回で実施したいと考えています。