前提・実現したいこと
お世話になります。
Laravelでクイズアプリを作ってみています。
「1度正解した問題を表示しない」という機能を実装したいです。
テーブルにはそれぞれ以下のようなデータが入っています。
・Questionsテーブル
idが問題番号、topic_idがカテゴリ、question_textが問題文です。
・Questions_optionsテーブル
question_idがQuestionsテーブルのidと関係しています。
correctがその選択肢が正解かどうかを表しています。
・test_answersテーブル
user_idが回答者のid、question_idがQuestionsテーブルのidと関係、correctが正解したかどうかを表しています。
入門書やネットで色々調べて試してみたのですがうまく行かず、初めて質問させていただきます。
SQLやPHPも学び始めたばかりですが、頑張りますのでご教授よろしくお願いします。
どのような関数を使えばいいのかやどういったサイトが参考になるのか等でも良いのでよろしくお願いいたします。
発生している問題・エラーメッセージ
1度解いて不正解になった(correctが0)問題のみ表示される...のはいいのですが、まだ1度も解いてない問題が、test_answersに登録されていないため表示されない。
また、実行してみるとこれまで表示されていた4択の選択肢が表示されなくなってしまいました。
今回の場合、topic_idが1、user_idが3で実行すると、test_answersテーブルのcorrectが0であるquestion_idが5と9の問題(中国の首都は?とスクリーンショットには載っていませんが9のイタリアの首都は?)のみ表示されます。
該当のソースコード
同じカテゴリ(topic_id)の問題からランダムで表示
php
1 /** 2 * 3 * 4 * @param int $id 5 * @return \Illuminate\Http\Response 6 */ 7 public function create($id) 8 { 9 // 元々書いてあったコード 10 // $questions = Question::where('topic_id', $id)->inRandomOrder()->limit(10)->get(); 11 12 // 今回書いているコード 13 $a_id = Auth::id(); 14 $questions = DB::table('questions') 15 ->where('topic_id', $id) 16 ->leftJoin('test_answers', 'questions.id', '=', 'test_answers.question_id') 17 ->where(function ($query) use($a_id){ 18 $query->where('test_answers.user_id', $a_id) 19 ->where('test_answers.correct', '<>', 1); 20 }) 21 ->inRandomOrder()->limit(10)->get(); 22 // 今回書いているコードここまで 23 foreach ($questions as &$question) { 24 $question->options = QuestionsOption::where('question_id', $question->id)->inRandomOrder()->get(); 25 } 26 return view('tests.create', compact('questions')); 27 }
補足情報(FW/ツールのバージョンなど)
・LaravelDailyさんのLaraQuizを元に作成しています。
https://github.com/LaravelDaily/Laraquiz-QuickAdminPanel
・環境構築にはMAMPを使っています。
・Question.php
php
1<?php 2namespace App; 3 4use Illuminate\Database\Eloquent\SoftDeletes; 5use Illuminate\Database\Eloquent\Model; 6 7/** 8 * Class Question 9 * 10 * @package App 11 * @property string $topic 12 * @property text $question_text 13 * @property text $code_snippet 14 * @property text $answer_explanation 15 * @property string $more_info_link 16*/ 17class Question extends Model 18{ 19 use SoftDeletes; 20 21 protected $fillable = ['question_text', 'code_snippet', 'answer_explanation', 'more_info_link', 'topic_id']; 22 23 public static function boot() 24 { 25 parent::boot(); 26 27 Question::observe(new \App\Observers\UserActionsObserver); 28 } 29 30 /** 31 * Set to null if empty 32 * @param $input 33 */ 34 public function setTopicIdAttribute($input) 35 { 36 $this->attributes['topic_id'] = $input ? $input : null; 37 } 38 39 public function topic() 40 { 41 return $this->belongsTo(Topic::class, 'topic_id')->withTrashed(); 42 } 43 44 public function options() 45 { 46 return $this->hasMany(QuestionsOption::class, 'question_id')->withTrashed(); 47 } 48}
・QuestionsOption.php
php
1<?php 2namespace App; 3 4use Illuminate\Database\Eloquent\SoftDeletes; 5use Illuminate\Database\Eloquent\Model; 6 7/** 8 * Class QuestionsOption 9 * 10 * @package App 11 * @property string $question 12 * @property string $option 13 * @property tinyInteger $correct 14*/ 15class QuestionsOption extends Model 16{ 17 use SoftDeletes; 18 19 protected $fillable = ['option', 'correct', 'question_id']; 20 21 public static function boot() 22 { 23 parent::boot(); 24 25 QuestionsOption::observe(new \App\Observers\UserActionsObserver); 26 } 27 28 /** 29 * Set to null if empty 30 * @param $input 31 */ 32 public function setQuestionIdAttribute($input) 33 { 34 $this->attributes['question_id'] = $input ? $input : null; 35 } 36 37 public function question() 38 { 39 return $this->belongsTo(Question::class, 'question_id')->withTrashed(); 40 } 41 42}
・TestController.php
php
1<?php 2 3namespace App\Http\Controllers; 4 5use DB; 6use Auth; 7use App\Test; 8use App\TestAnswer; 9use App\Topic; 10use App\Question; 11use App\QuestionsOption; 12use Illuminate\Http\Request; 13use App\Http\Requests\StoreTestRequest; 14 15class TestsController extends Controller 16{ 17 public function index() 18 { 19 $topics = Topic::all(); 20 21 return view('tests.index', compact('topics')); 22 } 23 24 /** 25 * 26 * 27 * @param int $id 28 * @return \Illuminate\Http\Response 29 */ 30 public function create($id) 31 { 32 // 元々書いてあったコード 33 // $questions = Question::where('topic_id', $id)->inRandomOrder()->limit(10)->get(); 34 35 // 今回書いているコード 36 $a_id = Auth::id(); 37 $questions = DB::table('questions') 38 ->where('topic_id', $id) 39 ->leftJoin('test_answers', 'questions.id', '=', 'test_answers.question_id') 40 ->where(function ($query) use($a_id){ 41 $query->Where('test_answers.user_id', $a_id) 42 ->Where('test_answers.correct', '<>', 1); 43 }) 44 ->orWhere(function ($query) use($a_id){ 45 $query->Where('test_answers.user_id', '<>',$a_id) 46 ->WhereNull('test_answers.question_id'); 47 }) 48 ->inRandomOrder()->limit(10)->get(); 49 // 今回書いているコードここまで 50 foreach ($questions as &$question) { 51 $question->options = QuestionsOption::where('question_id', $question->id)->inRandomOrder()->get(); 52 } 53 return view('tests.create', compact('questions')); 54 } 55 56 /** 57 * Store a newly solved Test in storage with results. 58 * 59 * @param \App\Http\Requests\StoreResultsRequest $request 60 * @return \Illuminate\Http\Response 61 */ 62 public function store(Request $request) 63 { 64 $result = 0; 65 66 $test = Test::create([ 67 'user_id' => Auth::id(), 68 'result' => $result, 69 ]); 70 71 foreach ($request->input('questions', []) as $key => $question) { 72 $status = 0; 73 74 if ($request->input('answers.'.$question) != null 75 && QuestionsOption::find($request->input('answers.'.$question))->correct 76 ) { 77 $status = 1; 78 $result++; 79 } 80 TestAnswer::create([ 81 'user_id' => Auth::id(), 82 'test_id' => $test->id, 83 'question_id' => $question, 84 'option_id' => $request->input('answers.'.$question), 85 'correct' => $status, 86 ]); 87 } 88 89 $test->update(['result' => $result]); 90 91 return redirect()->route('results.show', [$test->id]); 92 } 93 94 /** 95 * Delete all selected Test at once. 96 * 97 * @param Request $request 98 */ 99 public function massDestroy(Request $request) 100 { 101 if ($request->input('ids')) { 102 $entries = Topic::whereIn('id', $request->input('ids'))->get(); 103 104 foreach ($entries as $entry) { 105 $entry->delete(); 106 } 107 } 108 } 109}
・tests>create.blade.php一部抜粋
php
1@section('content') 2 <h3 class="page-title">@lang('quickadmin.laravel-quiz')</h3> 3 {!! Form::open(['method' => 'POST', 'route' => ['tests.store']]) !!} 4 5 <div class="panel panel-default"> 6 <div class="panel-heading"> 7 @lang('quickadmin.quiz') 8 </div> 9 <?php //dd($questions) ?> 10 @if(count($questions) > 0) 11 <div class="panel-body slider"> 12 <?php $i = 1; ?> 13 @foreach($questions as $question) 14 <div class="row"> 15 <div class="col-xs-12 form-group"> 16 <div class="form-group" style="padding-left:100px"> 17 <strong>Question {{ $i }}.<br />{!! nl2br($question->question_text) !!}</strong> 18 19 <input 20 type="hidden" 21 name="questions[{{ $i }}]" 22 value="{{ $question->id }}"> 23 @foreach($question->options as $option) 24 <br> 25 <label class="radio-inline"> 26 <input 27 type="radio" 28 name="answers[{{ $question->id }}]" 29 value="{{ $option->id }}"> 30 {{ $option->option }} 31 </label> 32 @endforeach 33 </div> 34 </div> 35 </div> 36 <?php $i++; ?> 37 @endforeach 38 </div> 39 @endif 40 41 </div> 42 43 {!! Form::submit(trans('quickadmin.submit_quiz'), ['class' => 'btn btn-danger']) !!} 44 {!! Form::close() !!} 45@stop
回答2件
あなたの回答
tips
プレビュー