Не записывать, если уже взяли, Laravel 5.7 (система викторин)

Я создаю систему викторин в Ларавель 5.7, и теперь я извлекаю вопросы из базы данных, и я должен применить условие, что если пользователь попытался задать вопрос, то не показывать этот вопрос пользователю снова, для этого я создал базу данных с именем как attempted_questions и два поля там как user_id и question_id и применил следующий код в контроллере:

class NewTestController extends Controller
{
    protected $question_id;
    public function nextQuestion(Request $request) {
        $attempted_questions = new AttemptedQuestion;
        $attempted_questions->user_id = Auth::id();
        $attempted_questions->question_id = $request->attempted;
        $attempted_questions->save();
        $question = Question::inRandomOrder()->first();
        $attempted = AttemptedQuestion::all();
        foreach ($attempted as $attempted) {
            while ($question->id == $attempted->question_id) {
                $question = Question::inRandomOrder()->first();
                $this->question_id = $question->id;
            }
        }
        return $this->question_id;
    }
}

Здесь сначала я получаю попытку вопроса от AJAX, а затем сохраняю текущего пользователя и question_id в базе данных, а после этого я получаю случайные вопросы из базы данных и после этого проверяю, есть ли уже заданный вопрос в базе данных? если нет, то покажите, иначе отобразите сообщение, но проблема здесь в том, что он также вызывает вопрос, который уже занят

не должно ли это условие быть while ($question->id != $attempted->question_id) { .

Dhaval Chheda 23.01.2019 05:48

нет, братан, я проверяю, если вопрос, который был взят, уже находится в базе данных попыток вопросов? если да, то снова ответьте на вопрос из БД, иначе нет!

Usman Developer 23.01.2019 05:52
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
2
121
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

У вас есть какая-то логическая ошибка. Вы задаете новый случайный вопрос в цикле while, избегая предыдущих вопросов, вот что я имею в виду:

Предположим, у вас есть 3 вопроса [1,2,3] и 2 попытки задать вопрос [1, 2].

Таким образом, в вашем цикле foreach вы зацикливаетесь на [1, 2], теперь вы находитесь на первой попытке вопроса, у которого question_id равен 1, в этот момент вы берете новый вопрос, скажем, его question_id равен 2. затем переходите к следующей итерации , второй attempted_question, у которого question_id равен 2.

здесь вы сравниваете последний результат с текущим attempted_question, и он равен, поэтому он удовлетворяет условию $question->id == $attempted->question_id, поэтому вы выбираете новый вопрос и случайно получили идентификатор вопроса 1. в этот момент вы не собираетесь проверять, равен ли он к первому attempted_question, потому что мы уже пропустили его из массива $attempted_questions.


лучшим решением было бы следующее:

возьмите все идентификаторы attempted_questions и используйте whereNotIn, чтобы получить все вопросы, которые не были предприняты.

$attempted = AttemptedQuestion::pluck('question_id');
$question = Question::whereNotIn('id', $attempted)->inRandomOrder()->first();

теперь у вас есть вопрос, который вы ищете.

Но вы экранируете, пытался ли текущий пользователь ответить на него или нет, поэтому вам, возможно, придется добавить некоторые операторы where для AttemptedQuestion для текущего пользователя следующим образом:

$attempted = AttemptedQuestion::where('user_id', Auth::id())->pluck('question_id');

Таким образом, вы можете получить что-то вроде этого:

class NewTestController extends Controller
{
    public function nextQuestion(Request $request) {
        $attempted_questions = new AttemptedQuestion;
        $attempted_questions->user_id = Auth::id();
        $attempted_questions->question_id = $request->attempted;
        $attempted_questions->save();
        $attempted = AttemptedQuestion::where('user_id', Auth::id())->pluck('question_id');
        $question = Question::whereNotIn('id', $attempted)->inRandomOrder()->first();

        return $question->id;
    }
}

Но это не проверено.

Надеюсь, поможет

Спасибо, братан, но я немного запутался, можешь отредактировать мой код?

Usman Developer 23.01.2019 06:03

p.s. вы можете проверить наличие $question==null и отправить сообщение пользователю, например, "Больше нет вопросов, пожалуйста, вернитесь позже" или что-то в этом роде.

Ahmed Nour Jamal El-Din 23.01.2019 06:10

ОМГ ОМГ ОМГ ОМГ ОМГ!!!!!!!! Люблю тебя брооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооооолив

Usman Developer 23.01.2019 06:11

рад, что это помогает ^^

Ahmed Nour Jamal El-Din 23.01.2019 06:12

На самом деле это довольно плохое решение. Потому что он извлекает все идентификаторы предпринятых вопросов. Поэтому, когда пользователь ответил на множество вопросов, это не будет масштабироваться... См. Мой ответ для обновленной версии.

user1415066 23.01.2019 10:17

вы должны игнорировать идентификатор текущего вопроса в вопросе о модели, также я не могу его увидеть, я так думаю

1

'Вопрос' => ['обязательно', 'описание', Rule::unique('user')->игнорировать($question->id)]

надеюсь, что это поможет!

Я бы пошел на следующее решение:

Question::whereDoestHave('attempts', function($query) {
     $query->where('user_id', Auth::id());
})->inRandomOrder()->take(1)->get();

Это будет работать, если вы определили следующее в своей модели вопросов:

public function attempts() {
    return $this->hasMany('App\Models\AttemptedQuestion');
}

Другие вопросы по теме