Дизайн базы данных для разработки веб-приложения Quiz с использованием PHP и MySQL - PullRequest
17 голосов
/ 18 августа 2011

Итак, я пытаюсь выучить PHP и MySQL (у меня есть базовое понимание обоих; я прочитал первую половину как Head First SQL, так и Head First PHP & MySQL), и я думаю, что лучший способ укрепить я знаю, что строю что-то, а не читаю.

Имея это в виду, я хотел бы создать базовую веб-страницу, которая подключается к базе данных MySQL на сервере. Я создам основную HTML-форму и позволю пользователям вводить основную информацию, такую ​​как: фамилия, имя, имя, адрес электронной почты, день рождения, пол.

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

Если бы вы могли помочь мне понять, как составить таблицы для викторины из 5 вопросов, я был бы признателен. Спасибо!

Ответы [ 4 ]

32 голосов
/ 18 августа 2011

Я бы начал с 4 простых таблиц:

 * User
   - user_id    auto integer
   - regtime    datetime
   - username   varchar
   - useremail  varchar
   - userpass   varchar
 * Question
   - question_id   auto integer
   - question      varchar
   - is_active     enum(0,1)
 * Question_choices
   - choice_id        auto integer
   - question_id      integer
   - is_right_choice  enum(0,1)
   - choice           varchar
 * User_question_answer
   - user_id      integer
   - question_id  integer
   - choice_id    integer
   - is_right     enum(0,1)
   - answer_time  datetime

Моя мысль об этом дизайне стола:

  • таблица User предназначена для хранения зарегистрированного пользователя.
  • таблица Question предназначена для хранения всех ваших вопросов. Он имеет is_active, так что вы можете выборочно отображать только активные вопросы (используя WHERE is_active = '1')
  • таблица question_choices предназначена для хранения всех доступных опций. Он имеет is_right_choice, который определяет, какой выбор является правильным ответом на конкретный вопрос.
  • Таблица User_question_answer предназначена для хранения ответов вашего пользователя. У него есть is_right для более быстрого поиска, чтобы увидеть, правильный ли этот конкретный вопрос и ответ (на основе ранее определенного is_right_choice). Он также имеет answer_time, чтобы отметить, когда именно этот пользователь отвечает на вопрос.
8 голосов
/ 18 августа 2011

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

Использование фреймворка поможет вам, предоставив передовой опытреализации инструментов, которые вам понадобятся в вашем проекте.

Я лично использую Symfony для проектов php, и я бы посоветовал вам проверить их руководства и учебные пособия .Symfony - это хорошо зарекомендовавший себя фреймворк, основанный на общепринятых разработках.

Чтобы ответить на ваш вопрос более прямо, я бы предложил нечто подобное для вашего приложения:

 - user
  - id (PK)
  - last_name
  - first_name
  - email
  - gender


 - quiz
  - id (PK)
  - title


 - quiz_question
  - id (PK)
  - quiz_id (FK)
  - text

 - quiz_question_option
  - id (PK)
  - quiz_question_id (FK)
  - text
  - is_correct

 - quiz_user_answer
   - id (PK)
   - quiz_question_id (FK)
   - quiz_question_option_id  // this is the answer.

Приведенное выше позволит вам определить несколько тестов, каждый из которых содержит несколько вопросов, и создать наборы ответов (набор ответов пользователя на тест) и записать каждый ответ.

Надеюсь, что это поможет:)

5 голосов
/ 18 августа 2011

Это был также первый проект, который я сделал в PHP / MySQL около 8 лет назад.

Ваше первое решение - это кодирование базы данных в точном соответствии с вашей формой.Итак, вы хотите записать пользователей и представления в викторине, чтобы это выглядело примерно так:

CREATE TABLE users (
  username VARCHAR(16) PRIMARY KEY, 
  password VARCHAR(8), 
  email VARCHAR(255), 
  birthday DATE, 
  gender ENUM('M', 'F')
);

CREATE TABLE quiz_answers (
  username VARCHAR(16) REFERENCES users,
  question1 VARCHAR(10),
  question2 INT,
  question3 ENUM('YES', 'NO', 'MAYBE'),
  question4 BOOLEAN,
  question5 VARCHAR(25),
  submitted_at DATETIME,
  PRIMARY KEY (username, submitted_at)
);

Так что это просто запись самого необходимого минимума: пользователь и представления в викторине.Я дал типы для ответов, которые вы должны были бы сделать конкретными для вашей реальной викторины.Я также сделал ответ, отключенный от пользователя и момент, когда они отправили его;у вас больше шансов использовать суррогатный ключ (AUTO_INCREMENT), но мне нравится как можно больше сопротивляться суррогатам.

Сразу же возникает нарушение 1NF: questionN.Если бы вы делали это правильно, вы бы назвали эти столбцы после того, как они означают, а не только по какому вопросу.Но нормализация это действительно следующий шаг к формам, которые расширяемы, но отслеживают историю.

Итак, следующее, что вы заметите, это то, что на самом деле тест представляет собой набор вопросов, каждый из которых имеет набор возможныхответы.И тогда отправка формы действительно связывает набор выбранных ответов на их вопросы, в определенной форме теста, от конкретного пользователя теста.Это звучит как четырехсторонние отношения: пользователь, тест, вопрос, ответ.Вы можете обрезать один из них, если не возражаете повторять вопросы о разных викторинах, но для полноты картины давайте пойдем по этому пути.Замените quiz_answers выше на это:

CREATE TABLE questions (
  id INTEGER AUTO_INCREMENT PRIMARY KEY,
  question TEXT
);

CREATE TABLE answers (
  id INTEGER AUTO_INCREMENT PRIMARY KEY,
  question_id INTEGER REFERENCES questions,
  answer VARCHAR(255)
);

CREATE TABLE quizzes (
  name VARCHAR(255) PRIMARY KEY,
);

У нас нет специальных метаданных для теста, поэтому пока это просто название.

Так что теперь вам нужно отношение один-ко-многим: от вопросов к ответам и от викторин к вопросам.

CREATE TABLE question_answers (
  question_id INTEGER REFERENCES questions,
  answer_id INTEGER REFERENCES answers,
  idx INTEGER,
  PRIMARY KEY (question_id, answer_id)
);

CREATE TABLE quiz_questions (
  quiz_name VARCHAR(255) REFERENCES quizzes,
  question_id INTEGER REFERENCES questions,
  idx INTEGER,
  PRIMARY KEY (quiz_name, question_id)
);

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

CREATE TABLE quiz_submissions (
  id INTEGER AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(16) REFERENCES users,
  quiz_name VARCHAR(255) REFERENCES quizzes,
  submitted_at DATETIME
);

CREATE TABLE submission_answer (
  submission_id INTEGER REFERENCES quiz_submissions,
  question_id INTEGER REFERENCES questions,
  answer_id INTEGER REFERENCES answers,
  PRIMARY KEY (submission_id, question_id)
);

Это довольно хорошо нормализовано на данный момент.Вы можете видеть, что запрос будет немного сложнее.Чтобы получить все вопросы для викторины, вам нужно присоединиться от викторины к вопросам.Вы можете либо присоединиться оттуда к ответам, чтобы выполнить один большой запрос, чтобы получить все данные, необходимые для построения формы (наряду с необходимостью дополнительной постобработки), либо вы можете попасть в базу данных еще раз для каждого вопроса и сделатьменьше пост-обработки.Я могу спорить в любом случае.Чтобы получить ответы всех конкретных пользователей, вам нужно будет выбрать из user_submissions с идентификатором викторины и именем пользователя в таблице submission_answer на вопрос и ответ, который выбрал пользователь.Таким образом, запрос станет интересным быстро.Вы потеряете свой страх перед объединениями, если он у вас будет.

Надеюсь, это не слишком сильно отстранит вас от реляционных баз данных;делая это, вы фактически создаете реляционную модель внутри реляционной модели, хотя и в ограниченной форме.

Я понимаю, что использование множества естественных ключей, как я делал выше, в наши дни немного неортодоксально.Тем не менее, я рекомендую вам попробовать, по крайней мере, в начале работы, потому что вам будет намного легче увидеть, как должны работать объединения, если они не все целые в диапазоне 1-10.

1 голос
/ 11 октября 2016

Хорошо, сейчас я нахожусь в стадии разработки и все еще сталкиваюсь с некоторыми проблемами (например, синхронизация раундов между сервером и клиентом), но это может вам помочь enter image description here

PS: не хранить пароли в базе данных, как на картинке выше - вместо них хранить хэши паролей

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...