福岡拠点の香月です。
今回はビューです。前回のルートとコントローラで呼び出されたURLに対してPHPでのプログラム処理ができるようになりました。
今回はここで実際にデータを集計して、結果を画面に表示したいと思います。この画面表示部分がMVCモデルのV(View)です。
Laravelの標準テンプレートエンジンはBladeとなっています。
それでは早速コントローラの実装です。
前回の実装ではLaravelのようこそ画面を呼び出していましたが、今回は”top”とう名前のテンプレートを使用して画面を表示するようにします。テンプレートファイルは後で作成します。
app/Http/Controllers/TopController.phpファイルを編集します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Score; use App\Student; use App\Subject; use Input; class TopController extends Controller { public function index(Request $request) { $dispday = $request->input('day'); $days = Score::getDays(); if (empty($dispday)) { $dispday = array_last($days); } $scores = Score::getList($dispday); $subjects = Subject::all(); $students = []; foreach ($scores as $score) { $name = $score->family_name . $score->first_name; if (!isset($students[$name])) { $students[$name] = []; } $students[$name][$score->subject_id] = $score->score; } return view('top') ->with('days', $days) ->with('dispday', $dispday) ->with('subjects', $subjects) ->with('students', $students); } } |
モデルScoreに追加した2つのメソッドを呼び出して得点に関するデータを取得しています(ソースは後ほど)。$daysには試験実施日の一覧が、$scoresには試験の点数データが入ってきます。
$subjectsでは科目一覧を取得しています。
$studentsは配列として定義していて、続くforeachで点数データ列挙しながら二次元配列を作成します。一次元目に生徒名、二次元目に科目ID、その値として点数を設定しています。
最後にreturn view(‘top’)で画面を呼び出すと同時に、topテンプレート内で使用するデータを->with()で指定しています。(->with()の複数回の呼び出しは、一回の->with()の呼び出しに置き換えることができます。その場合、->with()の引数にはキー、バリューの配列を設定します)
実装の先頭で$request->input(‘day’)を使っています。コントローラメソッド(ここでいうindex())ではメソッドインジェクション(依存注入機能)を使ってRequestクラスのインスタンスを取得することができ、ユーザーリクエストの内容を利用できます。
次はScoreにメソッドを追加します。app\Score.phpを編集しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Score extends Model { public static function getDays() { $scores = self::select('exam_day') ->groupBy('exam_day') ->orderBy('exam_day') ->get(); $days = []; foreach ($scores as $s) { $days[] = date('Y/m/d', strtotime($s->exam_day)); } return $days; } public static function getList($day) { $scores = self::whereDate('exam_day', $day) ->leftJoin('subjects', 'subject_id', '=', 'subjects.id') ->leftJoin('students', 'student_id', '=', 'students.id') ->orderBy('student_id') ->orderBy('subject_id') ->get(); return $scores; } } |
getDays()では試験日フィールドexam_dayをグルーピングして、日付の昇順に並び替えた結果を取得しています。exam_dayフィールドは時間まで入っているので、日付だけの書式に書き換えて配列に置き換えています。
getList()では引数で指定された試験日だけのデータを取得し、それに対してLEFT OUTER JOINで科目と生徒を連結した結果を返します。
さあ、ここまでくるとあとはビューを作成します。
resource/views/welcome.blade.phpをコピーしてresource/views/top.blade.phpを作成し、中身を編集します。
コントローラの最後で return view(‘top’) を呼び出していましたが、Laravelではこれでresource/viewsフォルダにあるtop.blade.phpの呼び出しと判断してくれます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<!doctype html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> : </head> <body> <div class="flex-center position-ref full-height"> <div class="content"> <div class="title m-b-md"> Score sheet </div> @foreach ($days as $day) @if ($dispday == $day) <span class="emphasis">{{ $day }}</span> @else <span><a href="{{ route('top') . '?day=' . $day }}">{{ $day }}</a></span> @endif @endforeach <table border="1" cellspacing="0" width="100%"> <tr> <td></td> @foreach ($subjects as $subject) <td>{{ $subject->name }}</td> @endforeach </tr> @foreach ($students as $name => $student) <tr> <td>{{ $name }}</td> @foreach ($subjects as $subject) <td>{{ $student[$subject->id] }}</td> @endforeach </tr> @endforeach </table> </div> </div> <br><br><br> </body> </html> |
画面のタイトル「Score sheet」を表示します。
その下には試験日の一覧$daysを@foreachで列挙して表示します。各試験日はaタグでリンクを作成し、クリックするとその日の表示に切り替わるようにしています。ここでroute(‘top’)を呼び出していますが、前回route/web.phpファイル内でRoute::get(‘/’, ‘TopController@index’)->name(‘top’);と指定した名前ですね。これによりこのリンク先が。/ に設定されます。
最後にtableタグで点数表を表示します。縦に生徒軸、横に科目軸を設定して、各生徒の点数を表示するようにしています。それぞれ@foreachでループしながらテーブルを生成しています。
これで実装が完了しました。実際に画面を表示して見ましょう。
表示するデータはシーダーで用意したデータです。
こんな感じで画面が表示されます。
Bladeテンプレートエンジンでは@foreach以外にも@if, @elseや@switch, @case, @breakなどの制御構文が使えます。
また、テンプレートの継承や@includeなど、他のテンプレートファイルと組み合わせて1つの画面を作成することができます。同じ内容を複数のファイルに書くと、後からの編集が大変ですね。その手間をなくすために積極的に活用しましょう。