Итак, я пытаюсь изучить PHP и MySQL (у меня есть базовое понимание обоих: я прочитал первую половину как First First SQL, так и Head First PHP & MySQL), и я считаю, что лучший способ укрепить мои знания путем создания чего-то, а не чтения.
Имея это в виду, я хотел бы создать базовую веб-страницу, которая соединяется с базой данных MySQL на сервере. Я создам базовую форму HTML и позволяю пользователям вводить базовую информацию, такую как: last_name, first_name, email, день рождения, пол.
Моя проблема заключается в том, что я не знаю, как создать базу данных, которая будет записывать результаты базовой викторины – мне нужно всего 5 проблем с множественным выбором. В конце концов, я хотел бы показать результаты пользователя по сравнению с результатами предыдущих пользователей.
Если бы вы могли помочь мне понять, как проектировать таблицу (ы) для 5-вопросной викторины, я бы ее оценил. Благодаря!
Я бы начал с 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
чтобы отметить, когда этот конкретный пользователь ответит на вопрос. Я не уверен, насколько вы новичок в программировании в целом, но даже если вы только начинаете, я бы рекомендовал использовать фреймворк.
Использование фреймворка поможет вам, предоставив наилучшие варианты реализации инструментов, которые вам понадобятся в вашем проекте.
Я лично использую 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.
Вышеупомянутое позволит вам определить несколько запросов, каждый из которых имеет несколько вопросов, и создавать наборы ответов (набор ответов пользователя для викторины) и записывать каждый ответ.
Надеюсь, это поможет 🙂
Это был первый проект, который я сделал в 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 с идентификатором викторины и именем пользователя в таблицу presentation_answer вопрос и ответ, который пользователь выбрал. Таким образом, запрос будет интересным быстро. Вы потеряете свой страх перед присоединением, если он у вас есть.
Надеюсь, это не слишком сильно избавит вас от реляционных баз данных; делая это, вы, по сути, делаете реляционную модель внутри реляционной модели, хотя и ограниченной формы.
Я понимаю, что использование многих естественных ключей, как я сделал выше, в наши дни немного неортодоксально. Тем не менее, я рекомендую вам попробовать, по крайней мере, в то время как вы начинаете, потому что это значительно упростит работу с соединениями, если они не все целые числа в диапазоне 1-10.
Ну, сейчас я на стадии разработки и все еще сталкиваюсь с некоторыми проблемами (например, синхронизацией состояний между сервером и клиентом), но это может помочь вам
PS: не храните пароли в базе данных, как на картинке выше – вместо этого сохраняйте хэши паролей