Laravelのみでクイズアプリを作る方法①クイズの作成と解答
2030 回閲覧されました
みなさんこんにちは、jonioです。
Laravelでクイズアプリを作ろうと思ってネットの情報を探したのですがVue.jsと連携して作る解説しかありませんでした。
私は何がなんでもLaravelだけで作りたかったので自作しましたが作り方が分からなくて困っている方がいるはずなのでその方の為に情報を残します。
話が長くなるので2回の記事に分けます。
目次
今回の記事の解説内容
クイズを作成して答える事ができる様にします。
2回目の解説で管理者のみが問題を作成する事ができる様にします。
注意点
ユーザー権限で表示を切り替えたり見る事ができないページのページを作っています。
Laravelを始めたてだと難しく感じる可能性が高いので難しいと思ったらその内容は実装せずクイズの機能だけを完成させて欲しいので今回の解説の内容だけ実装して下さい。
またHTMLとSCSSについて解説しないので分からない物は自分で調べて下さい。
Laravelのバージョン
8です。
開発環境
Laravel Sailです。
導入したい方は↓の記事からどうぞ。
ログイン機能
Breezeを使いました。
導入したい方は↓の記事からどうぞ。
デモ画像
トップページはログインとアカウント登録です。
ログインすると管理者かユーザーかで表示される内容が変わります。
↓は管理者の場合ですが「管理人用」で問題の作成ができます。
↓が問題を作成するページです。
作った問題に対する削除の機能はあえて入れていませんが導入したい方は↓を参考にして導入してみて下さい。
話を戻して↓はユーザーの場合です。
今回は実装していませんセキュリティ的にログイン画面にrecaptchaを実装した方がいいです。
導入したい方は↓からどうぞ。
問題画面は↓です。
「回答する」をクリックすると回答のページに移動して正解・不正解が分かります。
そして次の問題がある場合は次のページへのリンクが表示されます。
次の問題がない場合は「クイズが終了しました。」と表示されトップページに戻るリンクが付きます。
それではアプリを作っていきますがまずはクイズの機能だけを作ります。
それが終わったらユーザーの権限によって見る事ができないページを作りますのでLaravelを始めたての方はクイズの機能だけを完成するのを目指して下さい。
webpack.mix.js
scssを使うのでLaravelのプロジェクト直下にあるwebpack.mix.jsを↓にします。
cssしか使ってなくてscssが分からない方もいると思いますがその場合はコピペでいいです。
そして「Laravelのプロジェクト > resources」の下にsassフォルダを作ってその下にindex.scssとreset.scssを作ります。
index.scssを↓にします。
reset.scssを↓にします。
できたらターミナルで「sail npm run dev」を叩いて下さい。
これで全てのページの見た目を整える事ができるので中身を作っていきます。
ログインしたらリダイレクト
デフォルトの状態だとログインするとダッシュボードのページに移動します。
これをトップページに移動する様にします。
「Laravelのプロジェクト > app > Providers > RouteServiceProvider.php」の20行目辺りを修正します。(↓は20行目を修正しています)
そして「Laravelのプロジェクト > routes > web.php」を修正します。(コントローラー・ビューはすぐ作るので待って下さい)
「ルーティングの書き方が何か変だ」と思った方は↓に見慣れているかもしれません。
同じコントローラーに対してルート設定が複数ある場合は↓の書き方をした方がルート設定が楽です。
今のままだとコントローラーがないとエラーが出るので 「Laravelのプロジェクト > app > Providers > RouteServiceProvider.php」の29行目辺りを修正します。
29行目のコメントアウトになっている部分を外しました。
ではコントローラーとビューの作成をしますがまだコントローラーとビューがないのでトップページにアクセスするとエラーになります。
だからコントローラーとビューができるまでトップページにアクセスしないで下さい。
コントローラー
QuizControllerを作成します。
ターミナルで↓のコマンドを叩きます。
「Laravelのプロジェクト > app > Http > Controllers > QuizController.php」に記述します。
web.phpでアクション名を「index」にしていました。
次はビューを作成します。
ビュー
「Laravelのプロジェクト > resources > views」の下にquizフォルダを作成します。
そしてその下にindex.blade.phpを作成します。
index.blade.phpに記述します。
これでトップページにアクセスした時にログインしている場合・ログインしていない場合で表示を切り替える事ができます。
↓はログイン後です。
↓はログイン前です。
index.blade.phpのコードの説明をします。
コードの説明
16行目〜25行目ですが「@auth〜@else」がログインしている時で「@else〜@endif」がログインしてない場合です。
これでログインしている場合・ログインしてない場合で表示を切り替える事ができます。
9行目はアプリを公開した時に検索に引っかからない様にする為に付けました。
22行目の「{{ route(‘login’) }}」・23行目の「{{ route(‘register’) }}」ですがデフォルトで存在しているログインページ・アカウント登録ページを使っています。
問題を作成する
index.blade.phpの17行目ですが問題のページに移動できる様にする為に↓に修正します。
問題のページに移動する為のルーティング・コントローラー・ビューの記述をする前に問題を作成する為の記述をします。
テーブルの作成
問題情報を保存するテーブル名を「Questions」としたいのでモデル名を「Question」にします。
↓のコマンドを叩きます。
Questionsテーブルにカラムを追加する為にマイグレーションファイルに記述しますが「Laravelのプロジェクト > database > migrations > 本日の日付_create_questions_table.php」です。
21行目のquestionカラムは問題文用で22行目のchoicesカラムは解答の選択肢用のカラムで23行目のcorrect_choiceカラムは正解の選択肢用のカラムです。
choicesカラムのデータ型をjsonにしていますが問題を配列に格納する為です。
記述が終わったら「sail php artisan migrate」をするとテーブルにカラムが追加されます。
次はカラムに値を保存できる様にする為の記述をモデルにします。
モデル
「Laravelのプロジェクト > app > Models > Question.php」に記述します。
14行目〜18行目にテーブルに登録するのを許可するカラム名が書かれています。
20行目〜22行目ですがchoicesカラムの型を変換しています。
choicesカラムのカラムの型はjson(配列)でしたが今のままだとStringとして登録されます。
それを配列に変換して登録できる様にしています。
それでは問題を作成するページの表示・問題の登録をルーティング→コントローラー→ビューの順に記述します。
web.php(問題を作成するページの表示)
web.phpを↓にします。
コントローラー(問題を作成するページの表示)
QuizController.phpに記述します。
ビュー(問題を作成するページの表示)
quizフォルダの下にcreate.blade.phpを作成して何か適当に書いて下さい、後で中身を変えます。
それでは問題を登録できる様にします。
web.php(問題の登録)
web.phpを↓にします。
コントローラー(問題の登録)
QuizController.phpに記述します。
25行目〜29行目はバリデーションです。
問題文の作成・選択肢の作成・解答の選択を必須にしています。
31行目〜35行目で作成した問題文・選択肢・解答をデータベースのテーブルに保存しています。
31行目ができる様にする為に7行目があります。
情報を保存する為の記述は本来はモデルにすべきなのですが煩雑さを避ける為にコントローラーに記述しています。
ビュー(問題の登録)
先程作成したcreate.blade.phpに記述します。
これで「http://localhost/create」にアクセスすると↓になります。
create.blade.phpのコードの説明をします。
19行目・23行目・27行目・31行目・35行目のname属性がデータベースのquestionsテーブルのカラム名になります。
23行目・27行目・31行目のname属性の値が「choices[ ]」になっていますがchoicesカラムは解答の選択肢で配列で格納するからです。
↓はchoicesカラムの例です。
登録する際ですがコントローラーで問題文と選択肢の作成・解答の選択を必須にしているのでどれか1つが欠けているとエラーになりテーブルに保存がされません。
これで問題の登録は完成したので問題のページに移動して実際にクイズが表示されて答える事ができる様にします。
クイズのページに移動
クイズのページに移動できる様にする為にルーティング→コントローラー→ビューの順に記述します。
web.php(クイズのページに移動)
web.phpを↓にします。
34行目の「questionId」でデータベースのテーブルに登録されているクイズの問題にアクセスできる様になります。
QuizController.php(クイズのページに移動)
QuizController.phpにshowアクションを記述します。
16行目の「questionId」はweb.phpのquestionIdと同じで連動させています。
18行目のQuestion::findOrFail($questionId)ですが「モデル::findOrFail()」でテーブルの情報を取得できます。
ビュー(クイズのページに移動)
まずはログインしてから問題のページへのリンクをクリックした時に問題のページに移動できる様にします。
その為にトップページを表示するコントローラーからビュー(index.blade.php)に変数を渡します。
QuizController.phpを修正します。
15行目の「Question::where(‘id‘, ‘>=’ ,1)->first()」について説明します。
idはQuestionsテーブルのidカラムです。
「Question::where(‘id’, ‘>=’ ,1)->first()」でテーブルのidカラムの値が1以上に該当する最初のレコードの値を取得します。
↑の例だとid=6のレコードになります。
問題のページに移動して最初に表示される問題のレコードはwhere(‘id’, ‘>=’ ,1)に当てはまる最初の物でないといけないので->first()を使います。
「’id’, ‘>=’ ,1」の1ですが1にしないといけない理由は通常idの値は1から始まりますが↑の例の様にレコードを削除したらidの最初の値が1以外になります。
idの値が1の場合・1以上の他の値である場合も考えた上で「’id’, ‘>=’ ,1」にしています。
17行目の「firstQuestionId」をindex.blade.phpで使います。
index.blade.phpのコードを修正します。
17行目・18行目の「$firstQuestionId」がコントローラーから渡された値です。
17行目の「@if($firstQuestionId)」と19行目の「@endif」がある理由は問題が作成されていない状態だとquestionsテーブルのidカラムがなくて$firstQuestionIdがないのでトップページ(index.blade.php)があるページを表示するとエラーになるからです。
だからifを使って$firstQuestionIdがある(問題が作成されている)時だけ問題のページへのリンクが表示される様にしてエラーを回避しています。
それではクイズのページを作成します。
quizフォルダの下にshow.blade.phpを作成して記述します。
14行目の「{{ $question->question }}」で問題文を表示します。
18行目の「{{ $question->id }}」で表示されている問題のidカラムの値を取得します。(回答のページで使います)
19行目〜26行目が解答の選択肢になっています。
19行目の「choices as $index => $choice」ですが$index => $choiceが連想配列になっていて「$index」がkeyで「$choice」がvalueです。
19行目と22行目の「$index」が対応していて19行目と23行目の「$choice」が対応しています。
choicesは選択肢のカラムで配列の中には3つ入っています。
だから配列の中のインデックス番号は0・1・2です。
デベロッパーツールでも確認する事ができます。
だから22行目の「value=“{{ $index }}“」の「$index」が0・1・2に該当します。
これで問題のページが表示できたので次は解答のページを作成します。
解答のページ
先程作成したshow.blade.phpを修正します。
14行目を修正しました。
quizフォルダの下にanswer.blade.phpを作成して下さい。
それでは解答のページを表示できる様にしていくのでルーティング→コントローラー→ビューと記述していきます。
web.php(解答のページ)
web.phpに記述します。
QuizController.php(解答のページ)
QuizController.phpに記述します。
43行目は問題のページで選んだ選択肢を取得しています。
↓は問題のページのビュー(show.blade.php)です。
44行目は問題の内容を決めるidカラムの値を取得しています。
↓は問題のページのビュー(show.blade.php)です。
46行目の「$question->correct_choice – 1」の「-1」が付く理由は以下になります。
correct_choiceは問題を作成したページ(create.blade.php)の中にある選択した正解です。
selectタグの中にoptionタグがあってvalue属性がありますが値は1と2と3があります。
一方で問題の選択肢は配列に格納されているのでインデックス番号は0・1・2になります。
だから問題の選択肢の番号と正解の番号にズレがあるのでそれを埋める為に-1があります。
ビュー(解答のページ)
answer.blade.phpに記述します。
15行目の「+1」ですが先程説明した問題の選択肢の番号と正解の番号にズレがあるのを埋める為です。
17行目〜21行目ですが正解・不正解で表示の切り替えをしていて不正解の場合は正解が表示されます。
これで解答のページはできたので次の問題に移動できる様にします。
QuizController.phpのanswerアクションに追記します。
そしてanswer.blade.phpに追記します。
これで解答して次の問題があると次の問題へのリンクが表示されます。
問題がない場合はログイン直後のページに移動するリンクが表示されます。
ユーザーの切り替え
ログインした状態で「http://localhost/dashboard」にアクセスするとダッシュボードが表示されますのでそこからログアウトすればユーザーを切り替える事ができます。
これでクイズの問題を作って解答する機能は完成しました。
次回の解説
今の段階では誰でも問題を作る事ができますが管理人だけ問題を作る事ができるのが普通ですよね。
次回の解説ではユーザーの権限を振り分けて管理人だけが問題を作成できる様にします。