Ir para o conteúdo

Problemas comuns em código PHP

Esta página visa a cobrir alguns dos problemas mais comuns que acontecem no PHP. Por vezes são problemas simples, mas muito questionados em fóruns, etc. Vamos ver cada um deles pormenorizadamente.

Headers already sent

Problema: O código de PHP está todo bonito, quando, do nada, surge uma mensagem a dizer que os headers já foram enviados, por exemplo, com o seguinte código:

echo "oi";
header("Location: outrapagina.php");

Irá dar o seguinte erro:

Warning: Cannot modify header information - headers already sent by (output started at C:\wamp\www\probs.php:1) in C:\wamp\www\probs.php on line 2

Esta mensagem é bastante explícita: indica que os headers não podem ser enviados porque já ocorreu um output na linha 1 (echo "oi";).

E o que são os tais headers? São cabeçalhos HTTP que são enviados para o cliente com diversas informações, como a resposta do servidor (200 OK, 404 Not found), tamanho do ficheiro, etc.

Solução: Uma das soluções possíveis é garantir que não irá ocorrer nenhum output antes de ser enviado qualquer argumento na função header(). Alguns casos como exemplo:

echo "oi";
header("Location: outrapagina.php");

Neste excerto, a primeira linha pode ser descartada, uma vez que se o interesse é redireccionar para outrapagina.php, a mensagem, caso fosse possivel ter mostrá-la, não iria ser lida pelo cliente.

include("incluir.php");
header("Location: outrapagina.php");

À semelhança do código anterior, o ficheiro incluir.php poderá conter algum echo ou outra instrução que escreva para o browser.

Outra solução poderá ser activar o buffer que o PHP tem, para guardar todo o texto escrito nele, até pedirmos para o enviar para o browser. Vejamos o seguinte excerto de código:

// inciamos o buffer
ob_start();
echo "Menu: <a href=\"index.php?pag=comer\">Comer</a> | <a href=\"index.php?pag=dormir\">Dormir</a>";

// fazemos include da pagina pretendida
switch($_GET['pag']) {
case "comer":
    include("comida.php");
    break;
case "dormir":
    include("cama.php");
    break;
default:
    // dizemos a bots, etc, que a pagina nao existe
    header("404 Not Found");
}

// acaba aqui o nosso buffer
// Os headers que podiam ser enviados, já o foram
ob_flush();

Neste caso, queremos informar bots, por exemplo, de motores de busca, que se seguirem uma hiperligação que não tenha uma página a incluir, lhes seja enviado o erro 404, para que saibam que essa página não existe, e para que não a registem. Como existe um caso em que os headers podem ser enviados (se não existir a tal página, por exemplo, o utilizador seguiu index.php?pag=estudar), o buffer deve ser activado como medida de precaução.

Outra situação muito comum também tem a ver com a codificação do ficheiro. Alguns editores de texto colocam os documentos com codificação UTF-8, com um byte inicial, chamado Byte Order Mark (BOM), que é interpretado como um conjunto de caracteres (frequentemente se encontram sequências como  no início de documentos, isto indica a presença do BOM). Para o remover, deve-se ter o cuidado de gravar o ficheiro em formato UTF-8 sem BOM.

Sessões

Problema: As sessões devolvem-me um erro, de headers already sent, como o resolver?

echo "oi";
session_start();

E retorna o erro:

Warning: session_start() [function.session-start]: Cannot send session cookie - headers already sent by (output started at C:\wamp\www\probs.php:1) in C:\wamp\www\probs.php on line 2

Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at C:\wamp\www\probs.php:1) in C:\wamp\www\probs.php on line 2

Basicamente, as mensagens são bastante explícitas. O erro prende-se com o problema do output e dos headers. Para iniciar uma sessão, é necessário colocar um cookie com o ID da sessão. Ora, o cookie com PHP terá de ser enviado nos headers e como tal, não poderá haver outputs.

Solução: A solução, igualmente simples, poderá passar por colocar o session_start no topo do ficheiro:

session_start();
echo "oi";

Como ver o conteúdo de um array?

$meuarray = array("bananas", "laranjas",5, array(2,"sementes"));

echo "<pre>";
print_r($meuarray);
echo "</pre>";

Para obter também informação acerca do tipo de dados, usar a função var_dump em vez da print_r. Esta função mostra tambem o conteúdo de objectos.

$meuarray = array("bananas", "laranjas",5, array(2,"sementes"));
var_dump($array);

$string = "oiasdfoaisfd";
var_dump($string);

$boolean = false;
var_dump($boolean);

$nulidades = NULL;
var_dump($nulidades);

class MyClass {
 function metodo() {
  return "olá";
 }
}
$m = new MyClass;
var_dump($m);
var_dump($m->metodo());

Posso misturar conteúdos HTML e PHP no mesmo ficheiro?

Sim, é possível colocar código HTML e PHP no mesmo ficheiro. Contudo, é necessário seguir algumas regras para que o ficheiro funcione:

  • Se o ficheiro contém código PHP, então o ficheiro deve ter a extensão php (por omissão);
  • O código PHP deve estar correctamente delimitado por <?php e ?>;
  • Para escrever código HTML dentro do bloco de código PHP, deve-se usar uma função de escrita, tal como o echo.

O seguinte exemplo demonstra PHP e HTML no mesmo ficheiro, a funcionar correctamente:

<html>
<body>
<h1>A minha web</h1>
<?php
  $paragrafo = "<p>E aqui esta o meu paragrafo gerado dinamicamente pelo PHP</p>";
?>
<p>Aqui esta um paragrafo ja escrito no documento</p>
<?php 
  echo $paragrafo;
?>
</body>
</html>

O texto da minha página tem caracteres esquisitos

Se a página apresentar caracteres esquisitos, normalmente quadrados com pontos de interrogação, ou outros caracteres no lugar dos acentuados, significa que está a ser assumido um encoding diferente do pretendido. Deve-se ter em atenção alguns aspectos:

  • O tipo de encoding da página deve ser definido no HTML ou nos cabeçalhos HTTP (exemplo são UTF-8, ISO-8859-15, etc)
  • Não é boa prática escrever palavras acentuadas directamente no código-fonte. Devem ser usadas, em vez disso, html entities para os caracteres acentuados.

Uma forma rápida de resolver é indicar que a página está codificada em UTF-8, um padrão universal que abrange a maioria dos caracteres acentuados. Basta em PHP, antes de qualquer output, indicar a seguinte declaração:

header('Content-Type: text/html; charset=utf-8');