PHP header function

Hello everyone this is my first post. I’ve just bought the book develop app with PHP and MYSQL and i don’t understand why my exercise is not working as expected.

I have an index.html with inside a controller.
Inside index I can see a list of “jokes”, add a joke inside a database or delete it.Here the code of the index.php file

			//Se nell URL dell'header è presente la variabile addjoke, carica direttamente il form per aggiungere un joke
			if (isset($_GET['addjoke']))
			{
				include 'form.html.php';
				exit();
			}

			//Stabilisce la connessione al database e salva l'oggetto in una variabile pdo
			try
			{
			  $pdo = new PDO('mysql:host=localhost;dbname=joketable', 'root', 'root');
			  $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
			  $pdo->exec('SET NAMES "utf8"');
			}
			catch (PDOException $e)
			{
			  $error = 'Unable to connect to the database server.';
			  include 'error.html.php';
			  exit();
			}

			//Se la pagina riceve una variabile POST joketext, inserisce la nuova variabile nel database SQL
			if (isset($_POST['joketext'])) 
			{
				try
				{
					$sql = 'INSERT INTO joke SET
						joketext = :joketext,
						jokedate = CURDATE()';
					$s = $pdo->prepare($sql);
					$s->bindValue(':joketext',$_POST['joketext']);
					$s->execute();
				}

				catch (PDOException $e)
				{
					$error = 'Errore in aggiunta di joke inviato: ' . $e->getMessage();
					include 'error.html.php';
					exit();
				}

				//Alla fine del processo di salvataggio, ricarica la pagine corrente per mostrare l'ultima aggiunta
				header('Location: .');
				exit();
		  	}


		  	//se l'utente clicca su elimina nella riga del joke
		  	if (isset($_GET['deletejoke'])) {
		  		try{
		  			$sql = 'DELETE FROM joke WHERE id = :id';
		  			$s = $pdo->prepare($sql);
		  			$s->bindValue(':id', $_POST['id']);
		  			$s->execute();
		  		}
		  		catch (PDOException $e){
		  			$error = "Errore nell'eliminazione de joke: " . $e->getMessage();
		  			include 'error.html.php';
		  			exit();
		  		}
		  		header('Location: .');
		  		exit();
		  	}
		  	
			//Seleziona i joketext e salvali in una variabile result
			try 
			{
				$sql = 'SELECT id, joketext FROM joke';
				$result = $pdo->query($sql);
			}

			catch (PDOException $e)
			{
				$error = 'Errore in recupero joke: ' . $e->getMessage();
				include 'error.html.php';
				exit();
			}

			while ($row = $result->fetch())
			{
				//$jokes[] = $row['joketext'];
				$jokes[] = array('id' => $row['id'], 'text' => $row['joketext']);
			}

			include 'jokes.html.php';

Second file is the jokes.html.php that display all my jokes is used to add joke inside my databases. here the code:

		<body>
			<form action="?" method="post"> <!-- il ? dovrebbe rimuovere dalla URL tutti i campi e fare il redirect alla index, ma non funziona -->
				<div>
					<label for="joketext">Digita qui il tuo joke:</label>
					<textarea id="joketext" name="joketext" rows="3" cols="40"></textarea>
				</div>

				<div><input type="submit" name="Aggiungi"></div>
			</form>

		</body>

and finally the file form.html.php where is possible add joke to the database

		<body>
			<form action="?" method="post"> <!-- il ? dovrebbe rimuovere dalla URL tutti i campi e fare il redirect alla index, ma non funziona -->
				<div>
					<label for="joketext">Digita qui il tuo joke:</label>
					<textarea id="joketext" name="joketext" rows="3" cols="40"></textarea>
				</div>

				<div><input type="submit" name="Aggiungi"></div>
			</form>
		</body>

My problem is about the redirects after I add a joke or I delete it.
If I add a joke I’m redirected to this link http://localhost:8888/provePhp/jokes/? and the page is blank.
if I delete a joke instead I’m redirected to this link
http://localhost:8888/provePhp/jokes/?deletejoke and also here the page is blank.

It seems like the header function header(‘Location: .’) does not work or I made an error somewhere. If I add a joke I shoul be redirected to the index.php where all the jokes are displayed and also if I delete a joke the redirect shoul be the same. Anyone who can help me?
The exercise folder that I downloaded from the book it’s exactley the same but that one is working and not my example.

Hi there @daniele8808 welcome to the forums. I’m not au fait with the latest version of the book. However, I think we would need to see your complete index.php file to see what’s (not) happening.

hello here the all code of the index.php

	<!DOCTYPE html>
	<html>
	<head>
		<title>Index get addjoke</title>
	</head>
	<body>
	<?php 

	//Questo IF serve per disabilitare le magicquotes di PHP e non restituire errori nel caso in cui vengano usati caratteri strani all'interno di query SQL
	if (get_magic_quotes_gpc())
	{
	  $process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
	  while (list($key, $val) = each($process))
	  {
	    foreach ($val as $k => $v)
	    {
	      unset($process[$key][$k]);
	      if (is_array($v))
	      {
	        $process[$key][stripslashes($k)] = $v;
	        $process[] = &$process[$key][stripslashes($k)];
	      }
	      else
	      {
	        $process[$key][stripslashes($k)] = stripslashes($v);
	      }
	    }
	  }
	  unset($process);
	}

	//Se nell URL dell'header è presente la variabile addjoke, carica direttamente il form per aggiungere un joke
	if (isset($_GET['addjoke']))
	{
		include 'form.html.php';
		exit();
	}

	//Stabilisce la connessione al database e salva l'oggetto in una variabile pdo
	try
	{
	  $pdo = new PDO('mysql:host=localhost;dbname=joketable', 'root', 'root');
	  $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	  $pdo->exec('SET NAMES "utf8"');
	}
	catch (PDOException $e)
	{
	  $error = 'Unable to connect to the database server.';
	  include 'error.html.php';
	  exit();
	}

	//Se la pagina riceve una variabile POST joketext, inserisce la nuova variabile nel database SQL
	if (isset($_POST['joketext'])) 
	{
		try
		{
			$sql = 'INSERT INTO joke SET
				joketext = :joketext,
				jokedate = CURDATE()';
			$s = $pdo->prepare($sql);
			$s->bindValue(':joketext',$_POST['joketext']);
			$s->execute();
		}

		catch (PDOException $e)
		{
			$error = 'Errore in aggiunta di joke inviato: ' . $e->getMessage();
			include 'error.html.php';
			exit();
		}

		//Alla fine del processo di salvataggio, ricarica la pagine corrente per mostrare l'ultima aggiunta
		header('Location: .');
		exit();
  	}


  	//se l'utente clicca su elimina nella riga del joke
  	if (isset($_GET['deletejoke'])) {
  		try{
  			$sql = 'DELETE FROM joke WHERE id = :id';
  			$s = $pdo->prepare($sql);
  			$s->bindValue(':id', $_POST['id']);
  			$s->execute();
  		}
  		catch (PDOException $e){
  			$error = "Errore nell'eliminazione de joke: " . $e->getMessage();
  			include 'error.html.php';
  			exit();
  		}
  		header('Location: .');
  		exit();
  	}
  	
	//Seleziona i joketext e salvali in una variabile result
	try 
	{
		$sql = 'SELECT id, joketext FROM joke';
		$result = $pdo->query($sql);
	}

	catch (PDOException $e)
	{
		$error = 'Errore in recupero joke: ' . $e->getMessage();
		include 'error.html.php';
		exit();
	}

	while ($row = $result->fetch())
	{
		//$jokes[] = $row['joketext'];
		$jokes[] = array('id' => $row['id'], 'text' => $row['joketext']);
	}

	include 'jokes.html.php';
	?>

	</body>
	</html>

Your header redirect won’t work because you output all that HTML at the top of the page, before the opening <?php tag, and you can’t send headers after any output.

1 Like

I removed all the HTML at the top of the index but I was still getting the same error. Than I noticed that the first line of my index.php file was empty and my code was starting from the second line. I delete the first line and the code start working. I never heard this kind of problem leaving empty a line.

Don’t feel bad, I think leading whitespace causing headers to be sent has bitten just about everyone. It’s particularly pesky because whitespace isn’t visible and easy to miss as being the cause. But once it bites you won’t soon forget :kissing_cat:

2 Likes

I can relate.


Text Editors like gedit usually has an extra line break at the end of every file you edit and this may return headers already sent error for random white spaces. You can’t see it in gedit, but if you view the page source, you’ll see random line breaks where you haven’t actually added them in. Those are from gedit.

So don’t feel bad for not noticing the white space. It’s tough to find if you have thousands of files.

I dunno what book it is but it looks extremely outdated and misleading. There are three main problems with this code

  1. It is formally using PDO but doesn’t utilize PDO’s features and looks like rather bluntly rewritten from mysql_query version.
  2. Exceptions should be caught only once instead of bloating your code with repeated blocks.
  3. All the code that is using header() should be moved at the top, before any output.

Where the last one is the very reason for your problem. With the code below you will see not a single header related problem ever.

<?php
ini_set('display_errors',1);
error_reporting(E_ALL);

$pdo = new PDO('mysql:host=localhost;dbname=joketable;charset=utf8', 'root', 'root');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

if (isset($_POST['joketext'])) 
{
    $sql = 'INSERT INTO joke SET joketext = ?, jokedate = CURDATE()';
    $s = $pdo->prepare($sql);
    $s->execute([$_POST['joketext']]);
    header('Location: .');
    exit();
}

if (isset($_GET['deletejoke'])) {
    $pdo->prepare('DELETE FROM joke WHERE id = ?')->execute([$_POST['id']]);
    header('Location: .');
    exit();
}
?>
<!DOCTYPE html>
<html>
<head>
    <title>Index get addjoke</title>
</head>
<body>
<?php 
if (isset($_GET['addjoke']))
{
    include 'form.html.php';
    exit();
}
$jokes = $pdo->query('SELECT id, joketext text FROM joke')->fetchAll();
include 'jokes.html.php';
?>
</body>
</html>

programming is not about hunting whitespaces.

Come on, we’re programmers, not artists here to hunt a symbol around the pages. All you need is error reporting properly set for your project.

Once done, it will make PHP to tell you what’s the exact problem and where did it occur.

ini_set('display_errors',1);
error_reporting(E_ALL);

are the magic lines the will tell him what he has an empty line at the top of the script, with that notorious “Headers already sent” error message.

Beware, above script does not conform to PHP7’s stricter features.

Using the file wide strict declaration is preferable:

<?php

declare(strict_types=1);

ini_set('display_errors',1);// incorrect syntax
error_reporting(E_ALL);// -1 is more strict than E_ALL

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.