首页 > 解决方案 > 尽管方法被多次调用,但仅从 db 查询一次

问题描述

我正在尝试创建一个投票(测验)应用程序,现在我正在做一个从数据库中获取随机问题并在投票(测试)中返回的功能

我正在逐一显示答案,当用户单击提交答案时,会运行一个请求并显示下一个答案

问题是每次用户提交控制器都会被再次调用并且数据库查询也会被调用(当他点击下一个问题按钮时

这意味着查询现在会得到不同的随机问题,因为同样的问题有时会出现两次

我想确保获取问题的查询只被调用一次

模型:

private $random_questions;

public function getRandomQuestions($questions_count)
{
    if (!$this->random_questions)
    {
        $this->random_questions = Question::orderByRaw('RAND()')->take($questions_count)->get();
    }

    return $this->random_questions;
}

public function nextQuestionLink($questions_count, $question_number) {

    $nextQuestionLink = [];

    if ($questions_count != $question_number && $questions_count > $question_number) {
        $nextQuestionLink['url']   = '/polls/random/'.$questions_count.'/'.++$question_number;
        $nextQuestionLink['text']  = 'Следващ въпрос';
        $nextQuestionLink['class'] = 'btn-default';
    } else {
        $nextQuestionLink['url']   = '/result';
        $nextQuestionLink['text']  = 'Приключи';
        $nextQuestionLink['class'] = 'btn-primary';
    }

    return $nextQuestionLink;
}

控制器:

    public function getRandomQuestions($questions_count, $question_number)
    {
        $question = Question::Instance();
        $questions = $question->getRandomQuestions($questions_count);
        $nextQuestionLink = $question->nextQuestionLink($questions_count, 
        $question_number);

        return view('polls.random_questions_poll')->with([
            'question' => $questions[$questions_count-1],
            'next'      => $nextQuestionLink,
        ]);
    }

看法:

@section('content')

<div id="quiz-wrapper">
    <h1>{{ $question->question }}</h1>
    {!! Form::open(array( 'id' => 'message')) !!}
    {!! csrf_field() !!}
    @foreach($question->answers->shuffle() as $answer)
        <h3>
            <div class="form-group">
                <div class="radio">
                    {{Form::radio('result', "$question->id-$answer->id") }}
                    {{ Form::label('result', $answer->name) }}
                </div>
            </div>
        </h3>
    @endforeach
    <a class="next-question-button btn {{ $next['class'] }}" href="{{ $next['url'] }}" style="display: block;" role="button">{{ $next['text'] }}</a>
    <p id="validation-error-container"></p>
    {!! Form::close() !!}
</div>

@endsection

标签: phpmysqllaravel

解决方案


由于默认情况下 php 是无状态的,因此您需要将初始问题集存储在持久性存储中,并从中检索它们以供以后的所有请求使用。

您可以使用控制器中的会话非常简洁地做到这一点:

public function getRandomQuestions($questions_count, $question_number)
{
    //attempt to retrieve from session
    $questions = session('questions', function(){
        //if not found in session, generate from DB,
        $questions = Question::Instance()->getRandomQuestions($questions_count);
        //and store in session for next request.
        session(['questions' => $questions]);
        return $questions;
    });

    $nextQuestionLink = $question->nextQuestionLink($questions_count, 
    $question_number);

    return view('polls.random_questions_poll')->with([
        'question' => $questions[$questions_count-1],
        'next'      => $nextQuestionLink,
    ]);
}

推荐阅读