質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

Q&A

解決済

2回答

1059閲覧

Sessionを用いてクイズの解答制限をする方法【Laravel】

Tikka123456

総合スコア34

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

0グッド

0クリップ

投稿2021/05/03 06:06

編集2021/05/09 06:03

1日1回答えられるクイズサイトを作っています。
前回の質問でSessionを使った方が良いというアドバイスをいただき、実装しようと試行錯誤しましたが、Seesionを用いて解答済かどうかの処理をどのようにすれば良いのかわかりません。

OS:Mac M1
Laravel Framework 6.20.7

Quiz.vueのdata()内でisQuizFinishやisAlreadyAnsweredなどのクイズに解答したかどうかの変数が定義されていているのでこれを使いたいのですが、どうにもSessionと組み合わせて使う方法がわかりません。どうかよろしくお願いします。

Quiz.vue

<template> <div class="container is-fullhd"> <main> <div class="container"> <div class="notification"> <div class="columns"> <div class="card"> <div class="card-content"> <div class="column">   <section> <h2 cclass="title is-4"> 問題 </h2> <p>{{ title }}</p> <div class="quiz-answer__list"> <ul> <li v-for="(answer, index) in answers" :key="index"> <a> <button @click="goAnswer(index + 1)" :disabled="isAlreadyAnswered" class="button is-light is-fullwidth" >{{ index + 1 }}</button> </a> {{ answer }} </li> </ul> </div> </section> <section> <h2 class="title is-4"> 正解 </h2> <p> <button class="quiz-correct-answer button is-light is-fullwidth" v-show="isAlreadyAnswered" disabled >{{ correctAnswerNo }}</button> </p> <button @click="goAnswer(0)" v-show="!isAlreadyAnswered">正解を表示する</button> <div class="alert alert-info" v-show="isCorrect"> <strong>正解です</strong> </div> <div class="alert alert-danger" v-show="isMistake"> <strong>間違っています!</strong> </div> <div class="quiz-commentary__text" v-show="isAlreadyAnswered" style="white-space:pre-wrap; word-wrap:break-word;" >{{ commentary }}</div> <button type="button" data-toggle="modal" data-target="#modal-result" class="center-block" v-show="isQuizFinish" @click="showResult" >結果を見る</button> <button class="button is-info is-centered">クイズ一覧</button> </section> </div> </div> </div> <div class="submenu column is-4"> <the-sidebar></the-sidebar> </aside> </div> </div> </div> </div> </main> <the-modal :correctPercentageObject="correctPercentageObject" ref="modal" ></the-modal> </div> </template> <script> import TheSidebar from "../layout/TheSidebar"; import TheModal from "../module/TheModal"; export default { components: { TheSidebar, TheModal, }, mounted() { this.getQuiz(); }, data() { return { quizData: [], title: "", imageSrc: "", answers: [], commentary: "", correctAnswerNo: 0, isCorrect: false, //正解かどうか isMistake: false, //間違いかどうか isAlreadyAnswered: false, //回答済みかどうか isQuizFinish: false, //クイズが終了したかどうか score: 0, quizNumber: 1, correctPercentageObject: {}, }; }, methods: { getQuiz() { this.$http.get('/api/quiz') .then(res => { this.quizData = res.data const quiz = this.quizData[0] this.title = quiz.title this.answers = [ this.quizData[0].answer.answer_1, this.quizData[0].answer.answer_2, this.quizData[0].answer.answer_3, this.quizData[0].answer.answer_4 ]; this.commentary = this.quizData[0].answer.commentary; this.correctAnswerNo = this.quizData[0].answer.correct_answer_no; console.log(this.quizData); }) }, goAnswer(selectAnswerNum) { if (selectAnswerNum === 0) { this.isCorrect = false; this.isMistake = false; } else if (selectAnswerNum === Number(this.correctAnswerNo)) { // 正解を押した場合 alert-infoを表示し、alert-dangerを非表示にする そしてスコアを加算する this.isCorrect = true; this.isMistake = false; this.score += 1; } else { // 不正解の場合 alert-infoを非表示し、alert-dangerを表示にする this.isMistake = true; this.isCorrect = false; } this.isAlreadyAnswered = true; if (this.quizNumber >= 1) { this.endQuiz(); console.log(this.endQuiz()); } }, endQuiz() { this.isQuizFinish = true; this.answerNo = "-"; this.isAlreadyAnswered = true; this.correctPercentageObject = { correctScore: this.score, mistakeScore: 10 - this.score }; }, showResult() { this.$refs.modal.render(); } } }; </script>

web.php

<?php Route::get('/', function() { return view('quiz.index'); }); Route::get('/quiz', function() { return view('quiz.show'); });

api.php

Route::group(['middleware' => ['api']], function () { Route::get('quiz', 'Api\QuizController@show'); Route::post('quiz', 'Api\QuizController@store'); });

Quiz Controller.php

<?php namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; use Illuminate\Http\Request; class QuizController extends Controller { public function show() { $quiz = cache('quiz'); return $quiz; } public function store(Request $request) { $request->session()->put('Answertime', 19); $isAnswer = $request->session()->get('Answertime'); } }

Usersテーブル

<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('users', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('users'); } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

https://readouble.com/laravel/6.x/ja/session.html

LaravelのSessionのドキュメントを読んだでしょうか? 最初の方にセッションの設定はconfig/session.phpにあります。とかいてあります。その中に

'lifetime' => env('SESSION_LIFETIME', 120),

というのがあります。デフォルトだと120分なので、最低でも1440分(1日)に設定する必要があるでしょう。.envのSESSION_LIFETIMEに設定を追加し、php artisan config:cacheをする必要があります。その他の項目も適宜設定してください(expire_on_closeとか)。

あとはkeyとvalueでセッションデータを保存できるので回答したタイミングで最終回答時刻をセッションに保存し、問題を参照する際は

  • セッションデータと現在の時刻を突き合わせて1日以内に回答したデータがある

場合には問題データを返さず、それ以外の時は問題データを返すというようなコードをapiの中に書けばいいのではないでしょうか。

もう少し単純な実装にするなら、'SESSION_LIFETIME'を1440分に設定し、回答したタイミングでセッションに回答済みフラグをセットして、問題を参照する際は

  • セッションデータが存在する

場合に問題データを返さない、それ以外の時は問題データを返すというような実装だとコード量も経過時間を計算する処理の分だけ削減できると思います。

なお、このような実装の場合はVue側で回答したかどうかを変数で持っていてもあまり意味がないかもしれません。Vue側では問題が返ってこない場合(1日以内に回答済みの場合)の表示の制御の実装が肝となります。

投稿2021/05/04 17:02

編集2021/05/05 06:52
AbeTakashi

総合スコア4594

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Tikka123456

2021/05/05 06:40

詳しい回答ありがとうございます。質問なのですが、最終回答時刻はUserのテーブルにカラムとして追加して回答した際にSessionに保存するということでしょうか?
AbeTakashi

2021/05/05 07:04

SessionはDBとは違う概念です。Sessionを使うのであればDBは基本は関係ありません。その質問内容からするにあまりSessionの知識がないと思われますので、Sessionについて知識を深める必要かと思います。まずは生のPHPでのSessionの概念を理解した方が良いかもしれません。 参考) https://techacademy.jp/magazine/4970 ちなみにLaravelのSessionは独自実装なのでsession_start()や$_SESSIONは使いません。その点はご注意ください。どちらを使っても良いのですが、session_start()や$_SESSIONを使う場合はphp.iniでsession.gc_maxlifetimeやsession.cookie_lifetimeなどの設定の調整が必要となります。 参考) https://qiita.com/buntafujikawa/items/db3008bae3f7ce5d4c2a ユーザ認証前提ならSessionを一切使わずにDBを使う方法もありだと思いますので、その場合はUserテーブルのカラムに追加して最終回答時刻を保存するという方法でも実装は可能だと思います。
Tikka123456

2021/05/09 05:47

回答ありがとうございます。しばらく回答の通りに実装しようとしましたが、QuizControllerにSessionを保存して取得するよりを書いたのですがうまく動かず、どこに記述して良いのかわかりませんでした。または、api.phpのルーティングに書いたほうがいいのかわかりませんでした。
AbeTakashi

2021/05/09 06:38

どこに書いてもSessionは使えるとは思いますが、QuizControllerの中に書くのがオーソドックスじゃないですかね? storeメソッド内で回答した履歴をSessionに残し、showメソッド内でその履歴を元に1日以内にクイズに答えてるかの判別して、回答済みなら「今日は答えられません」的な情報をviewに渡して、そのように表示すればいいと思います。「うまくいかない」という表現だけでは残念ですが具体的なアドバイスはできません。
guest

0

セッションというよりはクッキーに保存すると良いのではないでしょうか?????

Laravel 8.x HTTPレスポンス レスポンスへのクッキー付加

補足というか思った事ですが、
1日1回の表現も24時間以内は回答できないのか、00:00過ぎたら回答できるようになるのか分からないので、人に説明する時は別の表現にした方がより良いかもです。

投稿2021/05/03 12:18

ucan-lab

総合スコア888

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Tikka123456

2021/05/04 13:53

ご指摘ありがとうございます。24時間以内は回答できないという意味です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問