Entry repeats on page refresh

I made myself a “To Do” list partly for php practice and partly because I don’t like any of the commercial ones. It works fine except for one issue that seems to crop up in my coding on occasion, and I can’t figure out why.

When I enter a task, and then refresh the page, the entry is duplicated in the display and in the database. The only time this doesn’t happen is if some items have already been marked as done, and moved to the bottom of the list. Also, when I select one of the duplicate entries and mark as done, both of them move down to the “done” list.

I tried initiating all the variables to empty at the beginning, and I tried commenting out my input value variables that I had included to retain state … nothing helped.

I can’t for the life of me find where the problem is originating. Could you please take a look and see what I did wrong? Thank you.

Here’s my code:

<?php
	// set error reporting, timezone, connect to database
	ini_set('display_errors',1); 
	error_reporting(E_ALL ^ E_NOTICE);
	require_once('inc/connect_db.php');
	date_default_timezone_set ("America/Toronto"); 
	
	// initiate date variables for use on page
	$current_date = date('M j, Y', time());
	$current_day = date('d', time());
	$current_month = date('m', time());
	$current_year = date('Y', time()); 
	$next_year = $current_year + 1;
	$current_date_stamp = mktime(0, 0, 0, $current_month, $current_day, $current_year);
	
	//initiate form variables
	$task = "";
	$project_id = "";
	$comments = "";
	$priority = "";
	$day = "";
	$year = "";
	$date_due = "";
	$cycle = "";
	$done = "";
	$submit = "";
?>

<?php
	// get header for page
	include_once('inc/header.php');
?>

<?php  
	//process the forms on the page
	if (isset($_POST['submit'])) {
		$submit = $_POST['submit'];
		
		// add a new task to the database and the job list
		if (isset($submit) && $submit == 'Add Task')	{
			$task = addslashes($_POST['task']);
			$comments = addslashes($_POST['comments']);
			$priority = $_POST['priority'];
			$month = $_POST['month'];
			$day = $_POST['day'];
			$year = $_POST['year'];
			$date_due = mktime(0, 0, 0, $month, $day, $year);
			$cycle = $_POST['cycle'];
			$done = 'n';
						
			$cycle = $_POST['cycle'];
			
			$query = "INSERT INTO todo
			SET task = '$task',
			comments = '$comments',
			priority = '$priority',
			date_due = '$date_due',
			cycle = '$cycle',
			done = '$done ' ";
			
			//print("<h6>$query</h6>");
			$result = mysql_query($query, $mysql_link);
			
		} else if (isset($submit) && $submit == "Done") {
		
			// update todo list to show 'done' items crossed out and placed at bottom of list
			$todays_task = $_POST['todays_task'];
			$num_tasks = count('$todays_task');
			
			//print_r($todays_task);
						
			foreach ($todays_task as $single_task) {
			
				//print("<h6>$single_task<br /></h6>");
				$single_task = addslashes($single_task);
				
				$query = "UPDATE todo
				SET done = 'y'
				WHERE task = '$single_task' ";
				
				//print("<h6>$query</h6>");
				
				$result = mysql_query($query, $mysql_link);
				
			}
			
		} else if (isset($submit) && $submit == "Update") {
			// delete all tasks for the day that are completed
			$query2 = "DELETE FROM todo
			WHERE done = 'y' ";
		
			$result2= mysql_query($query2, $mysql_link);
			unset($id);
			
			// On next day, take undone tasks and move them to the next day's date so they show up again
			//print("<h6>$current_date_stamp</h6>");	
			
			$query = "UPDATE todo
			SET date_due = '$current_date_stamp'
			WHERE done = 'n'	";
			
			//print("<h6>$query</h6>");	
			
			$result = mysql_query($query, $mysql_link);
		}
		
	}	

?>

<div id = "mainContent">
	<h2>To Do List</h2>
	<!-- Form for adding new items to the todo list -->	
	<div class="left">
		<form name="todoForm"id="todoForm"  method="post" action="todo.php">
			<h3>Add a New Task</h3>
			<label for="task" id="task_label">Task:</label><br /> 
				<input type="text" name="task" class="textbox" id="task" value="<?php //print $task; ?>" /><br /> 
			<label for="comments" id="comments_label">Comments:</label>
				<textarea name="comments"><?php //print $comments; ?></textarea>
			<label for="priority">Task Priority:</label>
				<select name="priority">
					<?php
					for ($i=0; $i<=3; $i++) {
						if ($_POST['priority'] == $i) {
							$selected = "selected=\\"selected\\"";
						} else {
							$selected = "";
						}
						print ("<option value=\\"$i\\" $selected>$i</option>");
					}
					?>
					
				</select>
				<!-- dropdown lists for entering the due date of the item (usually current day) -->
				<label for="deadline" id="deadline_label">Deadline:</label>
					<select name="month">
						<?php	$month = array(January, February, March, April, May, June, July, August, September, October, November, December);
						for ($i=0; $i<12; $i++) {
							$month_number = $i + 1;
							if ($_POST['month'] == $month_number) {
								$selected = "selected=\\"selected\\"";
							} else {	
								$selected = "";
							}
							print ("<option value=\\"$month_number\\" $selected>$month[$i]</option>");
						}
						?>
						</select>
						<select name="day">
							<?php
								for ($i=1; $i<=31; $i++) {
									if ($_POST['day'] == $i) {
										$selected = "selected=\\"selected\\"";
									} else {
										$selected = "";
									}
									print("<option value=\\"$i\\" $selected>$i</option>");
								}
							?>
						</select>
						<select name="year">
							<option value="<?php print $current_year; ?>"
								<?php
									if ($_POST['year'] == "$current_year") {
										print(" selected=\\"selected\\" >");
									} else {
										print(">");
									}
								?>
							<?php print $current_year; ?></option>
							<option value="<?php print $next_year; ?>"
								<?php
									if ($_POST['year'] == "$next_year") {
										print(" selected=\\"selected\\" >");
									} else {
										print(">");
									}
								?>
							<?php print $next_year; ?></option>
						</select><br />
						
						<!-- set up tasks to be automatically repeated (not coded yet - do at a later date)
						<label for="cycle">Task to be repeated </label>
						<select name="cycle" id="cycle">
							<option value="once">once</option>
							<option value="daily">daily</option>
							<option value="weekly">weekly</option>
							<option value="monthly">monthly</option>
							<option value="annually">annually</option>
						</select> -->
						<input type="submit" name="submit" id="submit" value="Add Task" />
		</form>
	</div><!-- end of left div -->
	
	<div class="right list leftborder">
		<h3>ToDo List for <?php print $current_date; ?></h3>
		<p>Click on task to show comments.</p>
		<form method="post" action="todo.php">
		
		<input type="submit" name="submit" class="done" value="Done" /><br /><!-- maybe a second 'done' button isn't needed? --->
		<?php  
			// select all items for the current day and display them, with a jquery slider to show the comments
			$query = "SELECT id, task, date_due, priority, comments, done
			FROM todo
			WHERE date_due = '$current_date_stamp'
			ORDER BY done ASC, priority ASC";
		
			$result = mysql_query($query, $mysql_link);
			$numrows = mysql_num_rows($result);
			
			if (mysql_num_rows($result) == 0) {
		?>
			<p>There are no tasks entered for today. Take a holiday!</p>
		<?php
			} else {
				
				while ($row = mysql_fetch_row($result)) {
					$task_id = $row[0];
					$task = stripslashes($row[1]);
					$date_due = $row[2];
					$priority = $row[3];
					$comments = nl2br(stripslashes($row[4]));
					$done = $row[5];
					
					switch($priority) {
					case 1:	
						$style = "style=\\"color: red;\\" ";
						break;
					case 2:
						$style = "style=\\"color: green;\\" ";
						break;
					case 3:
						$style = "style=\\"color: navy;\\" ";
						break;
					default:
						$style = "";
						break;
					}
					
					if ($done == 'n') {
		?>
						<p><input type="checkbox" name="todays_task[]" class="todays_task" value="<?php print $task; ?>" >
						<span class="task_name" <?php print $style; ?>><?php  print $task; ?></span></p>
						<p class="task_comments"><?php print $comments; ?></p>
						<input type="hidden" name="$id" value="<?php print $task_id; ?>">
		<?php				
					} else if ($done == 'y') {
			?>
						<p style="margin-left: 31px; font-weight: normal;"><span class="task_name complete" <?php print $style; ?>><?php  print $task; ?></span></p>
						<p class="task_comments complete"><?php print $comments; ?></p>
						<input type="hidden" name="$id" value="<?php print $task_id; ?>">
		<?php			
					}
				}
			}	
		?>
		<input type="submit" name="submit" class="button" value="Done" />
		<input type="submit" name="submit" class="button" value="Update" />
		<!--Note: the "Update" button removes all 'done' tasks from the list, and changes the date
		of the undone items to the current day so that they show up on the list again the next day.-->
		</form>
	</div><!-- end of right div -->
	<div class="clear"></div>
</div> <!-- end of mainContent div -->	

<?php
	include_once('inc/footer.php');
?>		

Hi WebMachine,

There are a number of ways to tackle reposting your form:

  1. Use javascript to redirect to another page
  2. Post using AJAX to another PHP page that processes the $_POST data via PHP. You can set a callback to return a success or failure code.
  3. Post to a php page that redirects you back to the same form page
  4. Upon submit, write a session value to indicate post has occurred, branch based on reading this value, clear $_POST and then remove the session variable

If you do any one of these things, you will not repost.

Steve

Thanks for the suggestions. I’ll go with option 4 because I am trying to keep all the code in one php file. I have used option 3 in the past (not knowing that by doing that I was avoiding this problem) to make the code easier to organize.

FWIW - I like #3