【laravel】カリキュラム参照機能を追加
本日はカリキュラム参照機能を実装しようと思います。
機能概要は、カリキュラム一覧ページから遷移して、カリキュラムページを表示させます。カリキュラムページは進んだり、戻ったりできるようにします。
またカリキュラムのページ1つに対して、1つのアクションを作ってしまうと管理が大変そうなので、カリキュラムページを表示させるアクション1つにします。
では早速実装していきましょう。
Tableを追加
DB Browserでcurriculum_progressionsテーブルを追加します。また、curriculumsテーブルにカラムを追加します。詳細は以下の通り。
curriculumsテーブル
- id
- name
- (追加)max_page INDEX
- (追加)created_at datetime
- (追加)updated_at datetime
max_pageはカリキュラムの全ページ数を格納します。このカラムを使って進捗率を表示予定。
created_atとupdated_atはカラムを追加(create)したり、更新(update)したりした時にその日時を格納するものです。laravelから追加更新する時に必要になります。
(追加)curriculum_progressionsテーブル
- id INTEGER PRIMARY KEY AUTOINCREMENT
- curriculum_id INTEGER
- user_id INTEGER
- current_page INTEGER
- created_at datetime
- updated_at datetime
カリキュラムの進捗を管理するテーブルです。ユーザ毎(user_id)、カリキュラム毎(curriculum_id)に何ページ(current_page)まで進捗しているかを保存します。
Modelを追加
次にテーブルに対応したモデルを追加します。モデルはテーブル内容を定義したクラスで、簡単にデータベースを操作することができます。
モデルとテーブルを関連付けるのは名前になります。テーブルは複数形、モデルは単数形にします。ただし、このルールに従わなくても、両者を関連付ける方法もあります。
モデルの追加は以下のコマンドで実施できます。
$ php artisan make:model Curriculum $ php artisan make:model CurriculumProgression
次にモデルとテーブルを関連付けます。テーブルを複数形、モデルを単数形とすれば自動で関連付けられるのですが、モデル名Curriculumに対応するテーブル名「curricula」なので今回は「curriculams」に変更します。
※初めからテーブル名をcurriculaとしておけば以下の記述は必要ありません。
Curriculum.php
class Curriculum extends Model { #テーブルと関連付ける protected $table = 'curriculums'; }
CurriculumControllerを修正
モデルが導入できたので、これらを使ってデータベースを操作しようと思います。
まずはカリキュラム内容を表示させるviewcurriculumアクションから実装していきます。ファイルはapp/Http/Controllers/CurriculumController.phpです。
少し長いですが、コードは以下です。
CurriculumController.php
public function viewcurriculum($id='1', $page='1') { $curriculum_id = (int)$id; $curriculum_page = (int)$page; $curriculum_page_next = $curriculum_page + 1; $curriculum_page_previous = $curriculum_page - 1; $user_id = (int)Auth::id(); #例のような文字列を生成・・・(例)curriculum.1.curriculum1_1 $viewfilename = 'curriculum' . '.' . $curriculum_id . '.' . 'curriculum' . $curriculum_id . '_' . $curriculum_page; #例のような文字列を生成・・・(例)http://localhost:8000/curriculum/1/2 $view_nexturl = url('/') . '/' . 'curriculum' . '/' . $curriculum_id . '/' . $curriculum_page_next; $view_previousurl = url('/') . '/' . 'curriculum' . '/' . $curriculum_id . '/' . $curriculum_page_previous; #初めてカリキュラムを参照するときは進捗状況を追加する if (CurriculumProgression::where(['user_id' => $user_id, 'curriculum_id' => $curriculum_id])->count() == 0) { $curriculumprogression = new CurriculumProgression; $curriculumprogression->fill(['user_id' => $user_id, 'curriculum_id' => $curriculum_id]); $curriculumprogression->save(); }
#カリキュラムンの全ページ数を取得 $curriculum_maxpage = Curriculum::where(['id' => $curriculum_id])->first()->max_page;
#カリキュラムの進捗を更新 $curriculumprogression = CurriculumProgression::where(['user_id' => $user_id, 'curriculum_id' => $curriculum_id]); if ($curriculum_page > $curriculumprogression->first()->current_page) { $curriculumprogression->update(['current_page' => (int)$curriculum_page]); }
#viewに送るデータを準備 $data = [ 'curriculum_id' => $curriculum_id, 'curriculum_page' => $curriculum_page, 'curriculum_page_next' => $curriculum_page_next, 'viewfilename' => $viewfilename, 'view_nexturl' => $view_nexturl, 'view_previousurl' => $view_previousurl, 'user_id' => $user_id, 'curriculum_maxpage' => $curriculum_maxpage, 'test' => $test, ];
#viewの表示 return view($viewfilename, $data); }
まず、本来であればモデルやミドルウェアに実装する処理も全てコントローラに記述しています。理由は私のスキル不足とまずは動くアプリを早く作りたいからです。
基本機能が全て完成して、時間があれば機能配置も考慮したコーディングに挑戦しようと思います。
それではviewcurriculumアクションの解説です。
変数の設定
まずviewcurriculumアクションはhttp://localhost:8000/curriculum/1/1のようにアクセスしてきた時に動くものとして設計しています。
curriculum/1/1の数字がそれぞれ、idとpageとしてアクションの中で使用します。
カリキュラの進む、戻るに対応するためにcurriculum_page_nextとcurriculum_page_previousを設定します。
これはカリキュラムページの順序が
curriculum/1/1 → curriculum/1/2 → curriculum/1/3 → curriculum/1/4
のようになっている前提での設定です。
Auth()::id()でログイン中のユーザのIDを取得できます。
ファイル名、リンクの設定
次に表示させるビューファイルを設定します。
ビューファイルは、resources/views/curriculum/1/curriculum1_1.blade.phpのように配置することにします。
curriculumテーブルのid=1の1ページ目のファイルがcurriculum1_1.blade.phpとなります。
ビューファイルを表示させる時はview(フォルダ名.ファイル名)の形式を取るので、「curriculum.1.curriculum1_1」という文字列を生成しています。
次にカリキュラムを進めたり、戻したりするリンクを作るために、URLを生成します。
ここでcurriculum_page_nextとcurriculum_page_previousを使います。
カリキュラム進捗状況の追加
次にカリキュラム進捗状況をモデルCurriculumProgressionを使って、追加します。
すでに進捗状況が設定されているときはこの処理は行いません。
user_idとcurriculum_idを追加していますが、モデルをこれをするためには事前に追加するカラムを設定して置く必要があります。
CurriculumProgression.php
class CurriculumProgression extends Model { //createする時にuser_idとcurriculum_idを許可 protected $fillable = ['user_id', 'curriculum_id']; }
これでnew→fill→saveでテーブルにレコード追加ができます。
カリキュラムの進捗を更新
次にカリキュラムの進捗を更新します。更新条件は「 閲覧ページ > 現在の進捗ページ 」としています。
先ほど追加したレコードのcurrent_pageカラムを更新します。
viewに送るデータを準備して、ページを表示
これまで生成してきた変数をdata配列にまとめて、viewメソッドでページを表示させます。
Viewを追加
次に表示させるビューを設定します。今回ベースレイアウトとセクションを使います。
ベースレイアウトは以下のように作りました。ファイルはresources/views/layouts/curriculumapp.blade.phpです。
curriculumapp.blade.php
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>@yield('title')</title> </head> <body> <header class="header"> <ul> <li><a href="{{ url('/') }}">Eravel</a></li> <li><a href="{{ url('/home') }}">MyPage</a></li> <li><a href="{{ url('/index') }}">Curricula</a></li> </ul> </header> <div class="content"> @yield('content') </div> </body> </html>
@yield('content')がセクション部分でカリキュラムのコンテンツそのもので、ページ毎に異なる内容になります。
それ以外は共通部分として使い回せるようにします。
続いて個別コンテンツです。ファイルはresources/views/curriculum/1/curriculum1_1.blade.phpです。
curriculum1_1.blade.php
@extends('layouts.curriculumapp') @section('title', 'curriculum_name') @section('content')
<p>ここにカリキュラム内容を記述</p> <p>curriculum_id: <?php echo $curriculum_id; ?></p> <p>curriculum_page: <?php echo $curriculum_page; ?></p> <p>user_id: <?php echo $user_id; ?></p> <p>curriculum_maxpage: <?php echo $curriculum_maxpage; ?></p> <a href="{{$view_nexturl}}">next_page</a> @endsection
extends('layouts.curriculumapp')で先ほど作成したベースレイアウトを指定します。
@section('content')〜@endsectionがメインコンテンツ部分でベースレイアウトの@yield('content')に対応します。
今の時点では具体的なコンテンツはありませんが、今後充実させていきます。
また1ページ目なので、previous_pageへのリンクはありません。2ページ目以降はnext_pageとprevious_pageの両方を設定します。
次にカリキュラム一覧ページから各カリキュラムの1ページ目に遷移できるように設定します。修正するファイルはresources/views/curriculum/index.blade.phpです。
index.blade.php
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>Eravel</title> </head> <body> <header class="header"> <ul> <li><a href="{{ url('/') }}">Eravel</a></li> <li><a href="{{ url('/home') }}">MyPage</a></li> </ul> </header> <p>hello Eravel</p> @foreach ($items as $item) <a href={{$item->getUrl()}}>{{$item->name}}</a><br> @endforeach </body> </html>
今回新たにgetUrl()を使っています。これはCurriculumモデルに以下のように定義しています。
public function getUrl() { return url('/') . '/' . 'curriculum' . '/' . $this->id . '/1'; }
各カリキュラムの1ページ目のリンクで例えば「http://localhost:8000/curriculum/1/1」のような形を返却するメソッドとなります。
ルートを設定
最後にルートを設定します。ファイルはroutes/web.phpです。
web.php
Route::get('/curriculum/{id?}/{page?}', 'CurriculumController@viewcurriculum');
idとpageに入る値で全てのカリキュラム内容を表示させるviewcurriculumアクションへのルートを設定しています。
おつかれさまでした。かなり長くなってしまいましたがこれでカリキュラムを表示させる部分の機能実装(基本部)を終わります。
実際のコンテンツやCSSやJSを使った飾りつけは後から行う予定です。