PHP Trivia Game - Day 2-3
Here is an updated version of the trivia game code, which has multiple screens (Welcome, Question) and fully-working sessions.
You can also play the game itself on this website!
/web/www/trivia/index.php
Unchanged from the starter code!
/web/src/trivia/TriviaController.php
Our updated controller.
<?php
class TriviaController {
private $questions = [];
private $db;
private $errorMessage = "";
/**
* Constructor
*/
public function __construct($input) {
// Start the session!
session_start();
$this->input = $input;
$this->loadQuestions();
}
/**
* 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":
$this->login();
break;
case "answer":
$this->answerQuestion();
break;
case "question":
$this->showQuestion();
break;
case "logout":
$this->logout(); // notice no break
case "welcome":
default:
$this->showWelcome();
break;
}
}
public function login() {
if (isset($_POST["fullname"]) && isset($_POST["email"]) &&
!empty($_POST["fullname"]) && !empty($_POST["email"])) {
// TODO: check that email looks right!
$_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;
}
$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.
*/
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;
}
/**
* Load questions from a file, store them as an array
* in the current object.
*/
public function loadQuestions() {
$this->questions = json_decode(file_get_contents("/opt/src/trivia/data/trivia-s25.json"), true);
}
/**
* 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) {
$randid = array_rand($this->questions);
// Add the question ID to the session
$_SESSION["qid"] = $randid;
return array_merge(["id"=>$randid], $this->questions[$randid]);
}
return array_merge(["id"=>$id], $this->questions[$id]);
}
/**
* 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
$name = $_SESSION["name"]; // name variable, make the template easier to read
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
unset($_SESSION["qid"]);
// Update the user's score
$_SESSION["score"] += 10; // + 10 points!
}
else {
$message = "<div class=\"alert alert-danger\" role=\"alert\">
Incorrect!
</div>";
}
}
$this->showQuestion($message);
}
}
/web/src/trivia/templates/welcome.php
The welcome template.
<!DOCTYPE html>
<html lang="en" data-bs-theme="light">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="author" content="CS4640 Spring 2025">
<meta name="description" content="Our Front-Controller Trivia Game">
<title>PHP Form Example - Trivia</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
</head>
<body>
<div class="container" style="margin-top: 15px;">
<div class="row">
<div class="col-xs-12">
<h1>Welcome to our Trivia Game!</h1>
<p>Please answer the questions below to begin playing</p>
</div>
</div>
<?=$message?>
<div class="row">
<div class="col-xs-12">
<form action="?command=login" method="post">
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control" id="name" name="fullname">
</div>
<div class="mb-3">
<label for="email" class="form-label">Email address</label>
<input type="email" class="form-control" id="email" name="email" aria-describedby="emailHelp">
<div id="emailHelp" class="form-text">We'll never share your email with anyone else.</div>
</div>
<div class="mb-3">
<label for="passwd" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password">
</div>
<button type="submit" class="btn btn-primary">Start</button>
</form>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
</body>
</html>
/web/src/trivia/templates/question.php
Our question template. Mostly unchanged! To update, simply print out the $name
above the Score.
/web/src/trivia/data/trivia-s25.json
Unchanged from starter code!