PHP Trivia Game - Database Edition
Here is an updated version of the trivia game code, which has multiple screens (Welcome, Question) and fully-working sessions. All files not listed are unchanged from the previous iteration of the trivia game.
/web/src/trivia/TriviaController.php
Our updated controller.
<?php
class TriviaController {
private $db;
private $errorMessage = "";
/**
* Constructor
*/
public function __construct($input) {
// Start the session! (new!)
session_start();
$this->db = new Database();
$this->input = $input;
}
/**
* Run the server
*
* Given the input (usually $_GET), then it will determine
* which command to execute based on the given "command"
* parameter. Default is the welcome page.
*/
public function run() {
// Get the command
$command = "welcome";
if (isset($this->input["command"]) && (
$this->input["command"] == "login" || isset($_SESSION["name"])))
$command = $this->input["command"];
switch($command) {
case "login": // new!
// TODO: maybe we should check name/email?
$this->login();
break;
case "answer":
$this->answerQuestion();
break;
case "question":
$this->showQuestion();
break;
case "logout": // new!
$this->logout(); // notice no break (new!)
case "welcome":
default:
$this->showWelcome();
break;
}
}
public function login() {
if (isset($_POST["fullname"]) && isset($_POST["email"]) &&
isset($_POST["password"]) && !empty($_POST["password"]) &&
!empty($_POST["fullname"]) && !empty($_POST["email"])) {
// TODO: check that email looks right!
$results = $this->db->query("select * from users where email = $1;", $_POST["email"]);
if (empty($results)) {
// create the user account
$result = $this->db->query("insert into users (name, email, password) values ($1, $2, $3);",
$_POST["fullname"], $_POST["email"],
password_hash($_POST["password"], PASSWORD_DEFAULT));
$_SESSION["name"] = $_POST["fullname"];
$_SESSION["email"] = $_POST["email"];
$_SESSION["score"] = 0;
// call showQuestion OR ...
// redirect with a header to the question screen
header("Location: ?command=question");
return;
} else {
// check that the user's password is correct
$hashed_password = $results[0]["password"];
$correct = password_verify($_POST["password"], $hashed_password);
if ($correct) {
// Success!
$_SESSION["name"] = $_POST["fullname"];
$_SESSION["email"] = $_POST["email"];
$_SESSION["score"] = $results[0]["score"];
// call showQuestion OR ...
// redirect with a header to the question screen
header("Location: ?command=question");
return;
} else {
$message = "<p class='alert alert-danger'>Incorrect password!</p>";
}
}
$this->showWelcome($message);
return;
}
$this->showWelcome("Name or email missing");
}
/**
* Logout function. We **need** to clear the session somehow.
* When the user wants to start over, we should allow them to
* reset the game. I'll call it logout, so this function destroys
* the session and immediately starts a new one. (new!)
*/
public function logout() {
// Destroy the session
session_destroy();
// Start a new session. Why? We want to show the next question.
session_start();
$_SESSION["score"] = 0;
}
/**
* Our getQuestion function, now as a method!
*/
function getQuestion($id = null) {
// Todo: Think about how to change this function to get
// the qid from the session rather than needing the id
// passed in. Would this be better?
if ($id == null) {
$results = $this->db->query("select id, question, answer
from questions order by random() limit 1;");
} else {
$results = $this->db->query("select * from questions where id = $1;", $id);
}
if ($results !== false && isset($results[0])) {
$_SESSION["qid"] = $results[0]["id"];
return $results[0];
}
// Look! We can throw exceptions like in Java!
throw new Exception("No questions in the database");
}
/**
* Show a question to the user. This function loads a
* template PHP file and displays it to the user based on
* properties of this object.
*/
public function showQuestion($message = "") {
$question = $this->getQuestion();
$score = $_SESSION["score"]; // score variable, make the template easier to read (new!)
$name = $_SESSION["name"]; // name variable, make the template easier to read (new!)
include("/opt/src/trivia/templates/question.php");
}
public function showWelcome($message = "") {
include("/opt/src/trivia/templates/welcome.php");
}
/**
* Check the user's answer to a question.
*/
public function answerQuestion() {
$message = "";
if (isset($_POST["answer"]) && isset($_POST["qid"]) && is_numeric($_POST["qid"])) {
$question = $this->getQuestion($_POST["qid"]);
if (strtolower(trim($_POST["answer"])) == strtolower($question["answer"])) {
$message = "<div class=\"alert alert-success\" role=\"alert\">
Correct!
</div>";
// Remove the question ID from the session (new!)
unset($_SESSION["qid"]);
// Update the user's score (new!)
$_SESSION["score"] += 10; // + 10 points!
$this->db->query("update users set score = $1 where email = $2;",
$_SESSION["score"], $_SESSION["email"]);
}
else {
$message = "<div class=\"alert alert-danger\" role=\"alert\">
Incorrect!
</div>";
}
}
$this->showQuestion($message);
}
}