mcq test application in php

MCQ test application in php




First of all Thank you very very much For your love and support we have reached 1k Like on FB PAGE so on this occasion i am releasing my new project “TestiFY” an online MCQ test application in php. This MCQ test application has good amount of feature. For this MCQ test application i have used Dirty PHP so that it will be easy for me to explain stuff to you guyz.




MCQ test application in php
Project Structure

MCQ test application in php

Database

Create a database with name testify
Create a table with name test

CREATE TABLE IF NOT EXISTS `test` (
  `id` int(11) NOT NULL,
  `name` text NOT NULL,
  `marks` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;

--
-- Dumping data for table `test`
--

INSERT INTO `test` (`id`, `name`, `marks`) VALUES
(1, 'PHP basics', 50),
(2, 'PHP Advance', 200),
(3, 'HTML', 120),
(4, 'C++', 150),
(5, 'Android Basics', 250);

ALTER TABLE `test`
  ADD PRIMARY KEY (`id`);

Create a table with name test_question

CREATE TABLE IF NOT EXISTS `test_question` (
  `id` int(11) NOT NULL,
  `test_id` int(11) NOT NULL,
  `question` text NOT NULL,
  `option1` text NOT NULL,
  `option2` text NOT NULL,
  `option3` text NOT NULL,
  `option4` text NOT NULL,
  `answer` text NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=latin1;

--
-- Dumping data for table `test_question`
--

INSERT INTO `test_question` (`id`, `test_id`, `question`, `option1`, `option2`, `option3`, `option4`, `answer`) VALUES
(1, 1, 'What does PHP stand for?', 'Hypertext Preprocessor', 'pretext Hypertext Processor', 'Preprocessor Home Page', 'Preprocessor', '1'),
(2, 1, 'PHP files have a default file extension of..', '.html', '.xml', '.php', '.ph', '3'),
(3, 1, 'A PHP script should start with ___ and end with ___:', '< php >', '< ? php ?>', '<?>', '<?php ?>', '4'),
(4, 1, 'Which of the below statements is equivalent to $add += $add ?', '$add = $add', '$add = $add +$add', '$add = $add + 1', '$add = $add + $add + 1', '2'),
(5, 2, 'Which version of PHP introduced the advanced concepts of OOP?', 'PHP 4', 'PHP 5', 'PHP 5.3', 'PHP 6', '2'),
(6, 2, 'Which one of the following is the right way to clone an object?', '_clone(targetObject);', 'destinationObject = clone targetObject;', 'destinationObject = _clone(targetObject);', 'destinationObject = clone(targetObject);', '2'),
(7, 2, 'If one intends to create a model that will be assumed by a number of closely related objects, which class must be used?', 'Normal class', 'Static class', 'Abstract class', 'Interface', '3'),
(8, 2, 'If your object must inherit behavior from a number of sources you must use a/an', 'Interface', 'Object', 'abstract class', 'static class', '1'),
(9, 2, 'Which feature allows us to call more than one method or function of the class in single instruction?', 'Typecasting', 'Method Including', 'Method adding', 'Method chaining', '4'),
(10, 2, 'Which magic method is used to implement overloading in PHP?', '__call', '__invoke', '__wakeup', '__unset', '1'),
(11, 3, 'A webpage displays a picture. What tag was used to display that picture?', 'picture', 'image', 'img', 'src', '3'),
(12, 3, ' <b> tag makes the enclosed text bold. What is other tag to make text bold?', '<strong>', '<dar>', '<black>', '<emp>', '1'),
(13, 3, 'Tags and test that are not directly displayed on the page are written in _____ section.', '<html>', '<head>', '<title>', '<body>', '2'),
(14, 3, 'Which tag inserts a line horizontally on your web page?', '<hr>', '<line>', '<line direction=”horizontal”>', '<tr>', '1'),
(15, 3, 'What should be the first tag in any HTML document?', '<head>', '<title>', '<html>', '<document>', '3'),
(16, 3, 'Which tag allows you to add a row in a table?', '<td> and </td>', '<cr> and </cr>', '<th> and </th>', '<tr> and </tr>', '4'),
(17, 3, 'How can you make a bulleted list?', '<list>', '<nl>', '<ul>', '<ol>', '3'),
(18, 4, 'What is data hiding ?', 'It is related with hiding internal object details', 'It is related with showing internal object details', 'It is related with datatypes', 'None of above', '1'),
(19, 4, 'What is class in c++ ?', 'When you define a class, you define a blueprint for a data type.', 'When you define a class, you make get more funtionality.', 'When you define a class, you define the logic.', 'When you define a class, you make debugging.', '1'),
(20, 4, 'What is object in C++ ?', 'Object is part of syntax of a class.', 'Object is datatype of a class.', 'Object is an instance of a class.', 'Object is function of a class.', '3'),
(21, 4, 'What is purpose of abstract class ?', 'to provide help with database connectivity.', 'to provide data input to other classes.', 'to provide security to other classes.', 'to provide an appropriate base class from which other classes can inherit.', '4'),
(22, 4, 'What is default visibility mode for members of classes in C++ ?', 'Private', 'Public', 'Protected', 'Depends', '1'),
(23, 5, 'Once installed on a device, each Android application lives in_______?', 'device memory', 'external memory', 'security sandbox', 'None of the above', '3'),
(24, 5, 'Parent class of Activity?', 'Object', 'Context', 'ActivityGroup', 'ContextThemeWrapper', '4'),
(25, 5, 'What are the indirect Direct subclasses of Activity?', 'LauncherActivity', 'PreferenceActivity', 'TabActivity', 'All the above', '4'),
(26, 5, 'Parent class of Service?', 'Object', 'Context', 'ContextWrapper', 'ContextThemeWrapper', '3'),
(27, 5, 'What are the indirect Direct subclasses of Services?', 'RecognitionService', 'RemoteViewsService ', 'SpellCheckerService', 'InputMethodService', '4');

ALTER TABLE `test_question`
  ADD PRIMARY KEY (`id`);

create a table with name test_taken

CREATE TABLE IF NOT EXISTS `test_taken` (
  `id` int(11) NOT NULL,
  `test_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `total` int(11) NOT NULL,
  `marks_obtain` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1;

--
-- Dumping data for table `test_taken`
--

INSERT INTO `test_taken` (`id`, `test_id`, `user_id`, `total`, `marks_obtain`) VALUES
(1, 1, 1, 50, 50),
(2, 5, 1, 250, 150),
(3, 4, 2, 150, 90),
(4, 2, 2, 200, 67),
(5, 3, 2, 120, 34),
(6, 1, 2, 50, 13),
(7, 5, 2, 250, 0),
(8, 4, 1, 150, 150),
(9, 1, 4, 50, 50),
(10, 2, 4, 200, 67);

ALTER TABLE `test_taken`
  ADD PRIMARY KEY (`id`);

Create a table with name user

CREATE TABLE IF NOT EXISTS `user` (
  `id` int(11) NOT NULL,
  `username` text NOT NULL,
  `password` text NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;

--
-- Dumping data for table `user`
--

INSERT INTO `user` (`id`, `username`, `password`) VALUES
(1, 'husain', 'test123'),
(2, 'ali', 'test123'),
(3, 'murtuza', 'test123'),
(4, 'hunk', 'test123');

ALTER TABLE `user`
  ADD PRIMARY KEY (`id`);

-- AUTO_INCREMENT for table `test`
--
ALTER TABLE `test`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=6;
--
-- AUTO_INCREMENT for table `test_question`
--
ALTER TABLE `test_question`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=28;
--
-- AUTO_INCREMENT for table `test_taken`
--
ALTER TABLE `test_taken`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=11;
--
-- AUTO_INCREMENT for table `user`
--
ALTER TABLE `user`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=5;

inc/connect.inc.php

In this file we are connecting to the database

<?php
	$con = mysqli_connect("localhost","root","","Testify");

	if(mysqli_connect_errno()){
		echo mysqli_connect_error();
	}
?>

inc/header.inc.php

in header we are including the connect.inc.php file

<?php require_once("connect.inc.php"); 
  session_start();
?>
<html>
<head>
	<title>Online Test Application with PHP and Mysqli</title>
  <link rel="stylesheet" href="css/bootstrap.min.css">
  <link rel="stylesheet" type="text/css" href="css/main.css">
</head>
<body>
	<!-- navbar -->
	<nav class="navbar navbar-default">
  <div class="container">
    <div class="navbar-header">
      <a class="navbar-brand" href="index.php">TestiFY</a>
    </div>
    <div>
      <ul class="nav navbar-nav pull-right">
        <?php
          /*menu when user is not loggedin*/
          if(isset($_SESSION&#91;'id'&#93;)){

            echo "
            <li><a href='index.php'>Test</a></li>
            <li><a href='leaderboard.php'>Leaderboard</a></li>
            <li><a href='logout.php'>Logout</a></li>";
          }else{/*menu when user is loggedin*/
            echo "<li><a href='login.php'>Login</a></li>
                  <li><a href='register.php'>Register</a></li>";
          }
          
        ?>
        
      </ul>
    </div>
  </div>
</nav>
	<!-- /navbar -->

inc/footer.inc.php

</body>
</html>



register.php

  1. One line 4 we are checking if user is loggedin we will send him to index.php
  2. From 23 we are waiting for register button to be clicked and then we are performing some check and storing the user info in `user` table
<?php require_once("inc/header.inc.php");

	/*send user to index.php if he is logedin*/
	if(isset($_SESSION&#91;'id'&#93;)){
		header("Location: index.php");
		exit();
	}
?>
<div class="container">
	<div class="form-container">
		<p class="heading text-center">Register</p>
		<form action="<?php echo $_SERVER&#91;'PHP_SELF'&#93; ?>" method="post">
			<div class="form-group">
				<input type="text" name="username" placeholder="Enter your Username" class="form-control" value="<?php echo @$username; ?>">
			</div>
			<div class="form-group">
				<input type="password" name="password" placeholder="Enter your Password" class="form-control" value="<?php echo @$password; ?>">
			</div>
			<input type="submit" value="Register" class="btn btn-primary" name="register">
		</form>
		<?php
			//login script
			if(isset($_POST&#91;'register'&#93;)){
				$username = trim(htmlspecialchars($_POST&#91;'username'&#93;));
				$password = trim(htmlspecialchars($_POST&#91;'password'&#93;));

				//if username or password is empty
				if(empty($username) || empty($password)){
					echo "<div class='alert alert-danger'>Fill in all the fields</div>";
					exit();
				}

				//check user is unique
				$unique = mysqli_query($con,"SELECT id FROM `user` WHERE username='$username'");
				if(mysqli_num_rows($unique) != 0){
					echo "<div class='alert alert-danger'>Username <strong>{$username}</strong> already registered.</div>";
					exit();
				}

				//check password length
				if(strlen($password) < 6){
					echo "<div class='alert alert-danger'>Password should be more the 6 characters</div>";
					exit();	
				}

				//insert into db
				$q = mysqli_query($con,"INSERT INTO `user` VALUES('','$username','$password')");

				if($q){
					echo "<div class='alert alert-success'>Registered</div>";
					$_SESSION['id'] = mysqli_insert_id($con);
					$_SESSION['username'] = $username;
					header("Location: index.php");
					exit();	
				}else{
					echo "<div class='alert alert-danger'>Failed to register user</div>";
					exit();
				}
			}
		?>
	</div>
</div>
<?php require_once("inc/footer.inc.php");?>

login.php

  1. on line 4 we are checking if user is loggedin send him to index.php
  2. on line 23 we are waiting for login button to be pressed
  3. On line 28 we are checking if username or password is empty so that we can so error message
  4. On line 34 we are fetching user information from the database
<?php require_once("inc/header.inc.php");

	/*send user to index.php if he is logedin*/
	if(isset($_SESSION&#91;'id'&#93;)){
		header("Location: index.php");
		exit();
	}
?>
<div class="container">
	<div class="form-container">
		<p class="heading text-center">Login</p>
		<form action="<?php echo $_SERVER&#91;'PHP_SELF'&#93; ?>" method="post">
			<div class="form-group">
				<input type="text" name="username" placeholder="Enter your Username" class="form-control">
			</div>
			<div class="form-group">
				<input type="password" name="password" placeholder="Enter your Password" class="form-control">
			</div>
			<input type="submit" value="Login" class="btn btn-primary" name="login">
		</form>
		<?php
			//login script
			if(isset($_POST&#91;'login'&#93;)){
				$username = trim(htmlspecialchars($_POST&#91;'username'&#93;));
				$password = trim(htmlspecialchars($_POST&#91;'password'&#93;));

				//if username or password is empty
				if(empty($username) || empty($password)){
					echo "<div class='alert alert-danger'>Fill in all the fields</div>";
					exit();
				}

				//check username and password match the db record
				$q = mysqli_query($con,"SELECT id FROM `user` WHERE username='$username' AND password='$password'");
				if(mysqli_num_rows($q) != 1){
					echo "<div class='alert alert-danger'>Invalid username or password</div>";
					exit();	
				}

				//fetch the if of the loggedin user start the session
				$row = mysqli_fetch_assoc($q);
				//set the session with loggedin user id
				$_SESSION['id'] = $row['id'];
				$_SESSION['username'] = $username;
				header("Location: index.php");
				exit();
			}
		?>
	</div>
</div>
<?php require_once("inc/footer.inc.php");?>

logout.php

<?php
	session_start();
	session_destroy();
	header("Location: login.php");
	exit();
?>

index.php

  1. On line 3 we are checking user is loggeding or not
  2. On line 16 we are fetching all the test from the `test` database
  3. On line 33 we are fetching the user score and displaying it
<?php require_once("inc/header.inc.php");
	/*send the user to login.php if he is not loggedin*/
	if(!isset($_SESSION&#91;'id'&#93;)){
		header("Location: login.php");
		exit();
	}else{
		$user_id = $_SESSION&#91;'id'&#93;;
	}
?>
	<div class="container">
		<!-- list all the online test -->
		<div class="col-sm-9">
			<h2 class="text-center">Online Test</h2>
			<?php
				//fetch all the test
				$q = mysqli_query($con,"SELECT * FROM `test`");
				while($row = mysqli_fetch_assoc($q)){
					$test_name = $row&#91;'name'&#93;;
					$test_id = $row&#91;'id'&#93;;
					echo "<div class='col-sm-6'>
							<div class='thumbnail text-center'>
								<h2>{$test_name}</h2>
								<a href='test.php?id={$test_id}' class='btn btn-primary btn-block'>Take Test</a>
							</div>
						</div>";
				}
			?>
		</div>
		<div class="col-sm-3">
			<h2 class="text-center">Welcome <?php echo $_SESSION&#91;'username'&#93;; ?></h2>
			<?php
				//Fetch total marks and marks obtained
				$q = mysqli_query($con,"SELECT * FROM `test_taken` WHERE user_id='$user_id'");
				if(mysqli_num_rows($q) == 0){
					echo "You have Not taken any test yet";
				}else{
					//display the score
					$total_marks = 0;
					$marks_obtained = 0;
					while($score = mysqli_fetch_assoc($q)){
						$total_marks += $score&#91;'total'&#93;;
						$marks_obtained += $score&#91;'marks_obtain'&#93;;
					}
					echo "<p>You got <strong>{$marks_obtained} Out Of {$total_marks}</strong></p>";
				}
			?>
		</div>
	</div>
<?php require_once("inc/footer.inc.php"); ?>

test.php

in this page we will list all the question from the database based on the id
MCQ test application in php

  1. on line 4 we will check user is loggedin or not
  2. on line 13 we will check test id is set or not
  3. on line 19 we will store test id in a variable $test_id
  4. on line 22 we are check $test_id is valid or not
  5. on line 37 we are checking that user has taken this test or not. If user has taken this test will show his result else display question of the test
  6. on line 52 we are displaying all the question based on the $test_id
  7. on line 74 we have a hidden input which store the $test_id so that we can evaluate the results in test_result.php
<?php
	require_once("inc/header.inc.php");
	/*send the user to login.php if he is not loggedin*/
	if(!isset($_SESSION&#91;'id'&#93;)){
		header("Location: login.php");
		exit();
	}else{
		/*store the loggedin id in a variable*/
		$user_id = $_SESSION&#91;'id'&#93;;
	}

	/*TEST id is not set OR TEST id is empty*/
	if(!isset($_GET&#91;'id'&#93;) || empty($_GET&#91;'id'&#93;)){
		header("Location: 404.php");
		exit();
	}

	/*store TEST ID in a variable*/
	$test_id = trim(htmlspecialchars($_GET&#91;'id'&#93;));

	/*check TEST ID is valid and exits in the database*/
	$testQ = mysqli_query($con,"SELECT * FROM `test` WHERE id='$test_id'");
	/*Invalid TEST ID*/
	if(mysqli_num_rows($testQ) != 1){
		echo "<h2 class='text-center'>Invalid Test ID</h2>";
		exit();
	}

	//store all the test information
	$test = mysqli_fetch_assoc($testQ);
	$test_name = $test['name'];
	$test_marks = $test['marks'];
?>
<div class="container">
	<?php
		/*check user has takken the test or not */
		$test_taken = mysqli_query($con,"SELECT * FROM `test_taken` WHERE test_id='$test_id' AND user_id='$user_id'");
		//means user has not taken this task
		if(mysqli_num_rows($test_taken) != 0){
			echo "<h2 class='align-center'>You have taken this test</h2>";
			//show the marks scored
			$testtaken = mysqli_fetch_assoc($test_taken);
			echo "<h3>You Scored <span>".$testtaken['marks_obtain']." Out Of ".$testtaken['total']."</span></h3>";
			
			exit();
		}
	?>
	<h2 class="text-center"><?php echo $test_name;?> - <span><?php echo $test_marks; ?> Marks</span></h2>
	<form action="test_result.php" method="post">
	<?php
		//display all the questions
		$questions = mysqli_query($con,"SELECT * FROM `test_question` WHERE test_id='$test_id' ORDER BY rand()");
		$i = 1;
		while($row = mysqli_fetch_assoc($questions)){
			$id = $row&#91;'id'&#93;;
			echo "<div class='thumbnail'>
			<p>{$i}-: ".$row['question']."</p>
				<div class='radio'>
  					<label><input checked type='radio' name='{$id}' value='1'> ".htmlspecialchars($row['option1'])."</label>
				</div>
				<div class='radio'>
  					<label><input type='radio' name='{$id}' value='2'> ".htmlspecialchars($row['option2'])."</label>
				</div>
				<div class='radio'>
  					<label><input type='radio' name='{$id}' value='3'> ".htmlspecialchars($row['option3'])."</label>
				</div>
				<div class='radio'>
  					<label><input type='radio' name='{$id}' value='4'> ".htmlspecialchars($row['option4'])."</label>
				</div>
			</div>";
			$i++;
		}
	?>
	<input type="hidden" name="test_id" value='<?php echo $test_id; ?>'>
	<input type="submit" value="submit" class='btn btn-primary'>
	</form>
	<br>
	<br>
</div>
<?php
	require_once("inc/footer.inc.php");
?>



test_result.php

In the file we are checking the answers of test and storing them into database `test_taken` table

  1. on line 14 we are storing the test_id from the hidden input field into $test_id
  2. on line 17 we are checking $test_id is valid or not
  3. on line 24 we are storing data from `test` table into a array of $row
  4. on line 31 we are calculating the marks for one question
  5. from line 38 we are checking answers of the test
  6. on line 55 we are storing them into `test_taken` table
<?php
	require_once("inc/header.inc.php");
	/*send the user to login.php if he is not loggedin*/
	if(!isset($_SESSION&#91;'id'&#93;)){
		header("Location: login.php");
		exit();
	}else{
		$user_id = $_SESSION&#91;'id'&#93;;
	}



	if (isset($_POST&#91;'test_id'&#93;)) {
		$test_id = $_POST&#91;'test_id'&#93;;

		/*check TEST ID is valid and exits in the database*/
		$testQ = mysqli_query($con,"SELECT * FROM `test` WHERE id='$test_id'");
		/*Invalid TEST ID*/
		if(mysqli_num_rows($testQ) != 1){
			echo "<h2 class='text-center'>Invalid Test ID</h2>";
			exit();
		}
		//get the total marks of the TEST
		$row = mysqli_fetch_assoc($testQ);
		$total_marks = $row['marks'];

		//fetch all the question with the test id
		$test_question = mysqli_query($con,"SELECT * FROM `test_question` WHERE test_id='$test_id'");

		//get the marks for one question
		$number_of_question = mysqli_num_rows($test_question);
		$each_marks = $total_marks / $number_of_question;

		$right_answers = 0;
		$wrong_answers = 0;
		$marks_obtained = 0;

		while ($question = mysqli_fetch_assoc($test_question)) {
			$question_id = $question['id'];
			$answer = $question['answer'];
			
			//check answer is right or wrong
			if($_POST[$question_id] == $answer){
				//add the right ans marks
				$marks_obtained += $each_marks;
				//mark one more answer as write
				$right_answers++;
			}else{
				$wrong_answers++;
			}

		}
		
		//insert into database
		$insert = mysqli_query($con,"INSERT INTO `test_taken` VALUES('','$test_id','$user_id','$total_marks','$marks_obtained')");

		header("Location: test.php?id={$test_id}");
		exit();
	}
?>

leaderboard.php

<?php
	require_once("inc/header.inc.php");
	/*send the user to login.php if he is not loggedin*/
	if(!isset($_SESSION&#91;'id'&#93;)){
		header("Location: login.php");
		exit();
	}
?>
	<div class="container">
		<?php
			//a array to store all the user TOTAL MARKS PERCENTAGE etc
			$leader = array();

			//fetch all the user from the database
			$q = mysqli_query($con, "SELECT * FROM 	`user`");
			while($row = mysqli_fetch_assoc($q)){
				$id = $row&#91;'id'&#93;;
				$username = $row&#91;'username'&#93;;
				
				//fetch all the mark with this $id
				$markQ = mysqli_query($con,"SELECT * FROM `test_taken` WHERE user_id='$id'");
				$total = 0;
				$mark_obtain = 0;
				while($r = mysqli_fetch_assoc($markQ)){
					$total += $r&#91;'total'&#93;;
					$mark_obtain += $r&#91;'marks_obtain'&#93;;
				}
				//if $total is equal to 0 means user has not taken any test so their is not need to show him in the leaderboard
				if($total != 0){
					//calculate the percentage
					$percentage = ($mark_obtain/$total) * 100;

					//store TOTAL ,MARKS_OBTAIN in leader array
					$leader&#91;$id&#93;&#91;'total'&#93; = $total;
					$leader&#91;$id&#93;&#91;'marks_obtain'&#93; = $mark_obtain;
					$leader&#91;$id&#93;&#91;'percentage'&#93; = $percentage;
					$leader&#91;$id&#93;&#91;'username'&#93; = $username;
				}
			}

			//sort the array by percentage
			function sortByPer($a, $b) {
    			return $a&#91;'percentage'&#93; + $b&#91;'percentage'&#93;;
			}

			usort($leader, 'sortByPer');
		?>
		<table class="table table-bordered thumbnail">
			<th>Rank</th>
			<th>Username</th>
			<th>Total Marks</th>
			<th>Marks Obtained</th>
			<th>Percentage</th>
			<tr>
			<?php
				$rank = 1;
				foreach($leader as $val){
					?>
					<td><?php echo $rank; ?></td>
					<td><?php echo $val&#91;'username'&#93;; ?></td>
					<td><?php echo $val&#91;'total'&#93;; ?></td>
					<td><?php echo $val&#91;'marks_obtain'&#93;; ?></td>
					<td><?php echo $val&#91;'percentage'&#93;; ?></td>
					</tr>
					<?php
					$rank++; //increase the ranks
				}
			?>
		</table>
	</div>
<?php
	require_once("inc/footer.inc.php");
?>

Demo

2 thoughts to “MCQ test application in php”

Leave a Reply

Your email address will not be published. Required fields are marked *