前回の続き。前回はfollowテーブルを作ってログイン中の社員が他の社員をフォローできるところまで作った。これだけでは何の意味も持たない機能なので、フォローしてる社員だけの日報をチェックできる画面を実装していくぜ。
フォローしてる社員の日報だけを表示するページを新たに作るのもありだが、今回は既存の日報一覧ページにチェックボックスを付けて、全件表示とフォロー表示で切り替えるようにする。
いたずらにページを増やすよりこっちの方が分かりやすいし、コーディング作業的にも既存のを流用できるので楽。
まずはこのチェックボックスを日報一覧のビューページにHTMLで追加するところから。
<div class="checkbox"> <c:choose> <c:when test="${follow_check == 1}"> <form method="GET" action ="<c:url value='/reports/index'/>"> <p><input type="checkbox" name="follow_check" value="1" checked="checked">フォロー中の日報のみを表示する <input type="submit" value="表示"></p> </form> </c:when> <c:otherwise> <form method="GET" action ="<c:url value='/reports/index'/>"> <p><input type="checkbox" name="follow_check" value="1">フォロー中の日報のみを表示する <input type="submit" value="表示"></p> </form> </c:otherwise> </c:choose> </div>
チェックボックスにチェックを入れて「表示」ボタンを押すと、follow_check変数1がパラメータとしてコントローラの方へ送られるようにした。whenタグで分岐させて2通り記述しているのは、一度チェックを入れて表示を切り替えたら、手動でチェックを外すまでデフォルトでチェックボックスにチェックが入った状態にしておきたいから。そうすれば、ユーザーも自分が現在全件表示をしているのか、フィルターをかけているのか常に分かりやすいので使い勝手がいい。
次にコントローラーの編集。まず、既存の全件表示がどんな仕組みになっているかというとこんな感じ。
既に、コントローラからListを受け取って、ビューで表示させるという枠組みはコーディング済みなわけだから、後はコントローラでListに詰め込むオブジェクトの内容を、チェックボックスのチェックの有無で切り替えできるようにプログラミングすればいいってわけ。
チェックボックスにチェックが入っていたら、reportテーブルから取得するデータは全件でなく、フォロー中の社員が書いたものだけにする。上の図のモデルのところに「likeテーブルに置いて、followeeが・・・」うんたらこうたら回りくどく書いてあるが、簡単に図で示すとこんな感じ。
これだけのことだが、日本語で示そうとするとさっきの図のように結構回りくどくなる。実際、同じ作業を職場の後輩に指示することを想定するとどうだろうか?
「まずログインユーザをemployeeテーブルで参照して、idを見つけてね。次にlikeテーブルを見て、followerがそのidになってるデータを全部見つけて。そしたらそのデータのfolloweeになっているemployee.idを全部リストアップして。最後にreportテーブルを全部チェックして、作成者がさっきのidになっているデータを一つ残らず記録しておいてね。report.idの昇順で並べておくんだよ」
長い。分かりにくい。多分絶対どっかでミスする。しかし、コンピュータが相手なら、次のようなSQL文で同じ指示ができる。
@NamedQuery( name = "getMyFollowReports", query = "SELECT r FROM Report AS r, Follow AS f WHERE f.follower =:employee AND r.employee = f.followee ORDER BY r.id DESC" ),
短い。そしてコンピュータは大抵間違えない。内部結合という、ちょっと特殊なSQL文だが、複数のテーブルを跨ぐ条件も上記のようなシンプルな文で指示できる。あとはemployeeという変数にログインユーザを代入してやれば、その人がフォロー中の社員が書いた日報のみを全件取得してくれるというわけ。
というわけで、このクエリを使ってコントローラーのコードを編集。
//省略 try { follow_check = Integer.parseInt(request.getParameter("follow_check")); } catch(Exception e){ follow_check = 0; } if (follow_check == 1){ int page; try { page = Integer.parseInt(request.getParameter("page")); } catch(Exception e){ page = 1; } List<Report> reports = em.createNamedQuery("getMyFollowReports", Report.class) .setParameter("employee", (Employee)request.getSession().getAttribute("login_employee")) .setFirstResult(15 * (page - 1)) .setMaxResults(15) .getResultList(); long reports_count = (long)em.createNamedQuery("getMyFollowReportsCount", Long.class) .setParameter("employee", (Employee)request.getSession().getAttribute("login_employee")) .getSingleResult(); request.setAttribute("reports", reports); request.setAttribute("reports_count", reports_count); request.setAttribute("follow_check", follow_check); request.setAttribute("page", page); } else { //省略
変数follow_checkが1になっている時だけ、先述のクエリで取得したreportオブジェクトをListに収めるようにしている。follow_checkの値はそのままスコープに入れてビューに送って循環させるようにしたので、任意でチェックボックスからチェックを外さない限り、ページ切り替えなどをしても状態が維持できる。
というわけでこれにてfollow機能は完成。お疲れ様っした。