Storing online exam results in sessions in PHP - php

I'm working on online free examination website. Using PHP, jQuery & session I'm displaying questions with choices on front end. If user clicks any choice among displayed choices (radio buttons with same name for all choices as obvious) I'm storing selected question number & choice (as answer1/answer2 up to answer2) in session variable, adding current quesno & choice to previous one.
The problem is if I want to change the answer which I'vE already answered, it's just appending as new result instead of updating.
I've tried to loop through that session variable but stuck. The following is the data format I'm storing into session variable.
if( $_POST['qno'] && $_POST['choice'] ){
$ques_no = $_POST['qno'];
$selected_choice = $_POST['choice'];// choices in radio buttons with name choice
if( isset($_SESSION['result']) ){
//here i'm trying to loop though $_SESSION['result'] to check the below format
>> ','.$ques_no.',' << in session so that it can be changed, i stuck here.
$_SESSION['result']=$_SESSION['result'].','.$ques_no.','.$selected_choice.'|';
}else{
$_SESSION['result'] = ','.$ques_no.','.$selected_choice.'|';
}
}
If this procedure is OK to follow please tell me the process of loop through and check whether that pattern existed in session or not; if it is wrong procedure please guide me.

The easiest way to accomplish this is to make $_SESSION['result'] an array rather than a string. Then you don't have to worry about if statements at all, except to make sure $_SESSION['result'] exists, you just assign the value in a single step and you're done:
if (!isset($_SESSION['result'])) $_SESSION['result'] = array();
$_SESSION['result'][$ques_no] = $selected_choice;
Just make sure you edit your other code to interpret $_SESSION['result'] as an array, or else you'll get some unexpected results.

I prefer you buy available online scripts in market as starting point for it. This will save you time, cost and testing efforts.
Below is one of the fine scripts that I worked it and it worked like charm. Using this as base I developed a online testing portal of over 1000 users using computer adaptive test.
http://codecanyon.net/item/online-skills-assessment/9379895
It is a good starting point for people looking to develop Online Exam System.

Related

Laravel - Is my double submission solution efficient

This my first question so please go easy on me. I have been using Laravel for a while; however, recently I have came across an issue in a client application while I was testing it.
The issue was if a user double submit or simply clicked submit button x times then the same record will be created x times in the database.
I have never faced this issue before simply because simple unique validation would achieve this.
Nevertheless, this form (or model to be exact) allows data with the same values/duplicates (client app requirement).
So the first thing I did was as follow:
public function store(CustomRequest $request)
{
if($lastEntry = Record::latest()->first()){
if(
($request->name == $lastEntry->name)
&& ($request->another == $lastEntry->another)
// && ($request->user()->id == $lastEntry->user_id) // Current user check (need to modify the $lastEntry for it to work efficiently!)
&& (now()->diffInMinutes($lastEntry->created_at) < 5) // I added this later as another way to allow duplicates records after each other if they were created 5m apart
){
return redirect()
->route('show.record', $lastEntry->id)
->with('success', 'Record has been created successfully.');
}
}
$record= new Record();
....
}
Now, after testing, it works great. But, my question is, are there any built-in solutions for this, packages or simply better ones?
Also, should I do a session solution for faster response - because, correct me if I am wrong but won't this be slow if it was on a table with > 500k records?
Edit: I thought about making a custom throttle middleware for this, but it would be kinda a bad idea, what do you think?
Also, as mentioned by #nice_dev with more users a double would occur so I thought about adding the user_id field in the record table and grabbed the last record the current user created but still I think it is a bad solution.
Javascript solution won't cut it unfortunately
Edit: What I meant by Javascript solutions, is the famouse once the button is clicked disable it kind of solution (any client-side solutions).
BTW, the client application will eventually have more than 500k record per table (at least in the first year or so).
Feel free to modify my question as you like ... like I said I am new here!.
Thanks in advance
Since, my situation is kinda unique I went with the same solution but added a user_id column on the records table (FK). And checked if the same record was created by the same user in the last x minutes (Since the client wants duplicate records but not allowing mistakes by the users).
Nevertheless, I added a javascript code to disable the button just in case. The client asked for a back-end solution not a client-side one. But might as well add that since I kinda solved the issue (kinda). Also, I created an indexing on the FK column as suggested by #nice_dev.
I had to come up with a solution fast. However, feel free to give your ideas/solutions.
Thanks!

how to get the old session?

I have a post form with captcha based on session for example the code know is Ujkd9 after refreshing the code become Hi8P4 .
And this is the problem. If someone post the form the captcha code of the input become old, how to get the old session ?
Well you can't, but you could save the older session into another session key creating a copy of that session, by example :
$_SESSION['session_copy'] = $_SESSION['current'];
I'm assuming your captcha code is being made on the fly and output via some image making in PHP. Your problem is that once you make the image and output it, you have no way to figure out what the CAPTCHA value actually is?
Since I have absolutely no knowledge of what your application structure, or database looks like, I can give you recommendations based on what I would do:
If I can assume that your PHP script looks something like this:
$captcha_string = make_hash(); // This function could just be the consolidation of your step in making the hash. I don't know, so it's going to be generic.
make_captcha_image($captcha_string); // Again, I don't know exactly how this goes, so I have to assume.
In layman's terms, you are going to need to store that somewhere. But Where? Now, I want it kept in mind that I've never particularly worked with Captcha directly, so I'm not 100% on what the "best practices" are, and I also don't know what you're doing, so these are probably going to be vague answers for a vague question. There are roughly 3 options, the way I see it.
1. Database Storage
Realistically, I would probably use a database as a first go-to. In my database I would have a table named captcha, with the following definition:
CREATE TABLE captcha (captcha_id int unique not null auto_increment, session_id VARCHAR(100) NOT NULL, captcha_string VARCHAR(6) NOT NULL)
Note: I don't know what length the session_id() function will return, and I am currently unable to check. If you know how long the session id is, change the length on session_id to match. Similarly for captcha_string I don't know how many letters your captcha will have. Change the definition to fit your uses.
What you are going to do, in words is:
Query the database with the current session_id to see if a captcha image exists.
set the information in a variable, I am using $captcha_data
If $captcha_data is populated with information, use its captcha string, otherwise, create a new on and store it.
Note that for this example, I assume that your database connection, whatever type it is, sits in an object named $db I am using no particular type of database, just methods I use in my own database class. The definitions would look similar for yours, but probably not exact.
$session_id = session_id();
$sql = "SELECT * FROM captcha WHERE session_id='".mysqli_real_escape_string($session_id)."'";
$result = $db->query($sql);
if($result!==false){
$captcha_data = $db->fetchrow($result);
}
$db->free_result($result);
$captcha_string = (isset($captcha_data['captcha_string'])) ? $captcha_data['captcha_string'] : make_hash(); // This function could just be the consolidation of your step in making the hash. I don't know, so it's going to be generic.
if(!isset($captcha_data['captcha_id'])){
$sql = "INSERT INTO captcha (session_id, captcha_string) VALUES('".mysqli_real_escape_string($session_id)."','".mysqli_real_escape_string($captcha_string)."')";
$db->query($sql);//You should check that this query is successful in your code, but for brevity I am skipping it.
}
make_captcha_image($captcha_string); // Again, I don't know exactly how this goes, so I have to assume.
Now keep in mind, I would probably add a date or time column to the captcha data so that I could delete values from accounts that haven't been used in some months, just to keep size down, but that's something I leave to you.
2. $_SESSION Storage
I can't say I recommend this option. It's effectively the same as my previous answer, just without the database interactions.
In words, we are doing the following:
Checking if the $_SESSION['captcha_id'] value is set, if so, use it. If not, create it.
This code is going to look very odd, so I recommend looking up Ternary Operators
//Assuming your session_start() is at the top of the page
$captcha_id = $_SESSION['captcha_id'] = (isset($_SESSION['captcha_id'])) ? $_SESSION['captcha_id'] : make_hash();
make_captcha_image($captcha_string);
3. File System Storage
I'd like to say that if this is the option you're choosing you've got some life decisions to make. This should not be used. Ever. Seriously.
That being said, the basic premise here is
See if a file with the current session_id exists.
if it does, read it's contents and use them as the hash for the image
else, create a new hash, create and populate the data in the file.
How that looks in Code:
$session_id = session_id();
if(file_exists('temp/'.$session_id.'.php')){
$captcha_string = $captcha_data = file_get_contents('temp/'.$session_id.'.php');
}else{
$captcha_string = hash();
file_put_contents('temp/'.$session_id.'.php',$captcha_string);
}
make_captcha_image($captcha_string);
Just to reiterate: don't use this method. I am supplying this answer simply and solely because your question asked HOW to keep the captcha from changing.

PHP visitor list array

I am currently working on my own shoutboxes using PHP, MYSQL and Jquery.
When a user has entered the shoutbox a message appears saying:
X has entered the shoutbox.
I do not want to store all visitors / users in MYSQL rows and so I was thinking I would need an array with a foreach script.
I'm not too sure how I should go about doing this, can someone please point me in the right direction?
Thank you
I assume you plan on storing this data in session? Depending on how you have session configured on your server, you may still be storing this data in a database (although the development effort may be less as you won't have to roll your own SQL to manage state).
The PHP manual has a section on arrays that sounds like it would be worth your time to read: http://php.net/manual/en/language.types.array.php. The manual has examples of adding objects to the array as well as looping through an existing array.
You could use a $_session variable, like when a user entered the shoutbox $_session->users[] = $user. $_session->users should be an array where you keep only their ids.

Session not incrementing correctly

I've been working on a little project that has gotten me turned on and off regarding mood. The problem which I've been having all from the start before I remade the application is that I try to increment a session called 'Score', but for some reason it won't increment. At a time I managed to get this working, but in the little time it did I didn't manage to find the root of the problem.
The application is just a simple word repeater/practicer. I have wordlists in .txt format which the application picks up, cuts out the lines and gives each word it's own session. Then it picks a random word and shows it to the user. If the word (array index) has already been used, it will be in an "used" array and cannot be chosen again.
When the user is presented a word, he is to type in the correct corresponding english (phonetic) word. After submitting the script will check if the POST value given corresponds with the answer stored in a session for that word.
Now, there is a session called 'Score'. This session is not changed unless User's Answer == Session's Answer (which is tested to work correctly). However, when those two answers are the same, the session does not increase. I have tried to use ++;, +1; and += 1;, none of which seems to be working. Also, I made the form submit to an external file to try and lessen the pain to see logic, in case you wondered.
I fail to see where I might have missed the logic and would be very grateful for any help as this project started off as something fun but has now just become a hassle:
Wordlists are structured like this: Cyrillic(RU) | Phonetic(RU) | English(answer).
HTML (index.php): http://pastebin.com/3ePLtzuj
PHP (engine.php): http://pastebin.com/pyXR2U2s
POST->PHP (wordcheck.php): http://pastebin.com/ZZxgkHkJ
wordcheck.php: check if $answer == $result is really true: var_dump($answer == $result);
your engine.php isn't included in your wordcheck.php if that does matter
check the existence of your session vars, before using them - like: $wordNum = isset($_SESSION['wordNum']) ? $_SESSION['wordNum'] : 0;

Checking if two ids are identical

I've added a feature to a web site that shows what visitors have visited a user profile. The table representing this holds the id of the user profile and the id of user visiting the profile.
Obviously, it's pointless showing that someone has visited their own profile so I modified the PHP code to detect this. In the meantime, a bit of data was written. This isn't a problem because it represents only a handful of users and I can edit the information by hand.
My question is as follows. In the hypothetical case where I'd have to do the same thing for more data, what would be a good approach to finding rows where id1 = id2 and removing them?
DELETE
FROM table
WHERE id1 = id2;
DELETE FROM `profiletracking` WHERE `visitor_id` = `profile_id`;
If you need to delete it, harakiri's query is good but I have a question, why to add a record in the first place? In time your website could grow bigger and things might get complicated.
I would suggest you to not record it to the database in the first place. You just do more actions and queries while there is a shorter way.
<?php
// Get ID of profile owner;
/* do your query here */
if ($_SESSION['id'] != $profileOwner['user_id']) {
// add it to your database
}
?>
I believe such approach is more elegant and useful, considering in the future your web site might grow bigger and you might need to check your codes again.
Please don't forget such things might be headache. This is a fatal mistake for a programmer. In the beginning, many thinks, ok for now this do the trick, why to bother coding more? In time you will add more and more codes, later you might lose yourself in it. It will be too late once your visitors / customer will start to complain about slow opening pages, eventually bad coding.

Categories