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

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

Laravel開発、複数削除処理に対応する【2】コンポーネント変更による、表示先に対応する

前回記事にて書籍情報の一括削除処理を完成させました。

しかし、一覧表示はコンポーネントとして作成していましたので、book.indexページからみた一覧表示に対しての削除処理は行えますが、他のページから同じコンポーネントを参照しても、作成したチェックボックス等が正常動作しません。

これらについても、正常動作出来るように対応させていきます。

今回の目的

書籍一覧コンポーネントを利用している他のページにもチェックボックスが表示されるので、正常動作するようにする

なぜやるか

全てのページにおいて正常動作する仕様とするため

やりたいこと

一覧表示コンポーネントで表示されるページを再度確認する

全てのページで用意したチェックボックスが正常動作し、扱える様にする

やったこと

一覧表示コンポーネント利用ページを確認する

書籍情報検索ページで使用出来るようにする

所有書籍ページでも使用出来るようにする

実施内容

コンポーネント使用ページを確認する

 

コンポーネントを利用しているページを見ていきます。

book.index

初めに表示される書籍情報の一覧表示画面です。

f:id:Fippiy:20190524140030p:plain

book.index表示(対応済み)

この画面は前回記事にて一括削除を実装済みです。

 

book.find

書籍情報の検索画面です。

f:id:Fippiy:20190524144330p:plain

book.find

一覧表示に同じコンポーネントを使用しているので、削除用の選択リストが表示されています。

 

property.index

ユーザーの所持している本のリスト表示です。

f:id:Fippiy:20190524144941p:plain

所有書籍一覧ページ

同じコンポーネントを利用してリスト表示していますので、チェックボック等も表示されます。

property.find

所有書籍情報の検索ページです。

f:id:Fippiy:20190524145003p:plain

所有書籍検索

こちらも同じコンポーネントを利用していますので、全く同じ表示方法で出力されます。

 

それぞれの表示ページに適合する処理となるように修正することで、全てのページで意味のある動作ができるようにしていきます。

 

検索ページを修正する

書籍情報検索ページ

まずは検索ページのリストです。ここ画面での動作は書籍の一覧表示同様にデータ削除ができれば問題ありません。

リストが肥大化してくると、タイトルで検索して一覧から削除する場面もあるかもしれません。

 

コンポーネントでの標記はこうなっていました。

[編集後]

# ~/resources/views/components/books_list.blade.php

<div class="book-table">
 @if (isset($books))
  <form action="{{ route('book.some_delete') }}" method="post">
   <div class="book-table__btn">
    <span>操作:</span>
    <input type="submit" class="book-table__btn--delete" value="書籍情報一括削除">
   </div>

 

しかし、初めに作成していた時の記述は少し異なっていました。

[修正前]

<div class="book-table">
 @if (isset($books))
  <form action="book/some_delete" method="post">
   <div class="book-table__btn">
    <span>操作:</span>
    <input type="submit" class="book-table__btn--delete" value="書籍情報一括削除">
   </div>

アクションに個別に位置を指定していました。この状態では、書籍一覧ページは~/book、検索ページは~/book/findと階層が異なっていた為に正常に動作しませんでした。

route記述化することでこの問題は解決し、どちらのページでも動作してくれるようになりました。

ルート名についてはルーティング標記にて設定しています。

# ~/routes/web.php

// ログイン必須ページ
Route::group(['middleware' => ['verified']], function () {
 Route::post('/book/somedelete', 'BookController@somedelete')
  ->name('book.some_delete');
});

somedeleteアクションに対して名前を付与し、これを指定することで階層に関係なく指定した名前のアクションが行われるようになりました。

これで、書籍情報の一覧表示ページと検索ページからは正常に削除出来るようになりました。

 

所有書籍ページを修正する

所有書籍一覧リストの動作をどうするか

書籍情報の削除はできるようになりましたが、ユーザーが持っている本の一覧にも削除フォームは表示されています。 

property.index

f:id:Fippiy:20190524144941p:plain

所有書籍一覧

ここはあくまで所持している本であり、本自体の情報を載せているページではありません。

所有している本の情報なので、手放した際に所有情報から解除する動作として機能させることにしました。

property.find

f:id:Fippiy:20190524145003p:plain

所有書籍検索

所有書籍の検索結果にも同様のフォームが表示されます。こちらも所有書籍一覧ページと同様に所有情報から解除する動作として処理できるようにします。
 

コンポーネントを修正する

書籍情報と所有書籍では処理する内容が異なるので、処理を分岐させます。

今までの一覧表示内容も処理内容が異なっており、スロットによって処理を分けていました。

 

書籍情報のindexからコンポーネントの参照をどうしていたかというと…。

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

@component('components.books_list',['books'=>$books])
 @slot('page_path')
  book
 @endslot
 @slot('detail')
  detail
 @endslot
@endcomponent

page_path=bookとdetail=detailと個別に値を設定していました。

 

# ~/resources/views/property/index.blade.php

@component('components.books_list',['books'=>$books])
@slot('page_path')
property
@endslot
@slot('detail')
freememo
@endslot
@endcomponent

propertyページからは、スロットに対しての値が異なっています。

 

これらは、一覧表示に使用するデータが異なるために個別に設定していました。

こちらの設定を利用して、一覧表示のフォームアクションを分岐させることにしました。

 

スロット情報を利用してフォームアクションを分けます。

# ~/resources/views/components/books_list.blade.php

<div class="book-table">
@if (isset($books))
@if ($page_path == 'book')
<form action="{{ route('book.some_delete') }}" method="post">
@else
<form action="{{ route('property.some_delete') }}" method="post">
@endif 

コンポーネント内の記述でpage_pathによるページ種類設定があったので、これを利用してif分岐させました。所有書籍の場合はproperty.some_deleteアクションとすることで、所有書籍に対する処理として扱うことができます。

検索ページにも同様にスロットを設定しているので、この変更だけで一覧表示ページと検索ページ両方に対応できます。

 

propertyコントローラーを作成する

後は、所有書籍情報に対しての一括削除処理を作成していきます。

# ~/app/Http/Controllers/PropertyController.php

public function somedelete(Request $request){
 // フォームデータ取得
 unset($request['_token']); // トークン削除
 $datas = $request->input('select_books'); // 削除書籍情報をフォームから取得
 $count = count($datas); // 取得件数
 // 取得データなければ処理中止
 if ($count == 0) {
  // 削除情報が1件もないときはバリデーションエラーにする
  $validator = Validator::make(['deleteproperty' => false],
   ['deleteproperty' => 'accepted'], ['所有書籍から解除する本が選択されていません']);
  if ($validator->fails()) {
   return redirect('property')
    ->withErrors($validator)
    ->withInput();
  }
 }
 // 複数登録同様に結果配列をつくる
 // 処理用配列へ追加
 $i = 1; // 結果出力番号
 foreach($datas as $data){
  // 一度に削除できる上限数で処理を停止
  if ($i > 20){
   break;
  }
  // 配列格納
  $deleteproperties[] = array(
   'process' => 'processing', // 処理中ステータス
   'number' => $i, // 番号
   'property_id' => $data, // 所有書籍から解除するid
   'msg' => null, // 処理テキスト
  );
  $i++;
 }
 // 削除の実行
 for ($i = 0; $i < $count; $i++){
  if ($deleteproperties[$i]['process'] == 'processing'){
   // 削除レコード取得
   $delete_property = Property::find($deleteproperties[$i]['property_id']);
   // 本人の場合のみ削除実施
   if ($delete_property['user_id'] == Auth::user()->id){
    // レコード削除
    $delete_property->delete();
    data_set($deleteproperties[$i], 'title', $delete_property->bookdata->title);
    // 表示タイトル名を追加
    data_set($deleteproperties[$i], 'msg', "所有書籍から解除しました");
    // メッセージを追加
    data_set($deleteproperties[$i], 'process', 'completion'); // 処理ステータス変更
   }
  }
 }
 return view('property.delete_result',['answers' => $deleteproperties]);
}

処理の流れは書籍情報削除時と同じです。所有書籍に関する値取得に変更すれば完了です。

 

最後に処理結果画面を用意し、実際に所有書籍情報が削除できれば完了です。

f:id:Fippiy:20190524155050p:plain

所有書籍削除

タイトル名を配列に残しておき、結果として出力できれいれば完了です。

 

以上で一覧表示コンポーネントを使用している各画面にて全ての処理ができるようになりました。

画面操作上で問題なく動作していますが、引き続きテストも行っていきます。