Problemas com codificação: acentos não interpretados

Problemas com codificação: acentos não interpretados

Um dúvida muito recorrente em fóruns concerne a erros com acentuação, quando palavras como “atenção” são exibidas como “aten??o”. Ou ficam com caracteres estranhos, como na imagem acima.

A solução geralmente é muito simples: padronizar as codificações de arquivos, do banco de dados e do HTML.


A melhor codificação a ser usada é a UTF-8, que suporta diversos idiomas, e tem sido adotada como codificação padrão em diversas aplicações.

E importante manter todas as codificações iguais, ou seja, todas em UTF-8. Para um site, é preciso atentar para as seguintes codificações:

Codificação do arquivo propriamente dito

É a codificação do arquivo dentro do sistema operacional. Ela pode ser modificada por meio do seu editor de textos (Sublime, Notepad++, Eclipse, Netbeans e outros). Também é possível alterar a codificação de um arquivo com o comando iconv, em ambientes Linux ou Mac OS X, da seguinte forma:

$ iconv -f codificacao_original -t utf-8 arquivo > arquivo_utf8

Para mais detalhes sobre como usar o comando iconv, veja este tutorial.

UTF-8 Sem BOM

O BOM (Byte Order Mark, ou Marca de Ordem de Byte) é uma sequência de
caracteres que é inserida no início de um arquivo para definir a ordem dos bytes. Isso é uma razão de um dos principais problemas com o uso de sessões e cookies, como descrevo aqui.

Por isso use sempre UTF-8 sem BOM e não terá problemas.

Codificação do HTML

A codificação do HTML é definida por meio de meta tag ou da função header(), do PHP.

Definição por meio de meta tag, para HTML 5:

<meta charset="utf-8" />

Definição por meio de meta tag, para HTML 4 e XHTML:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

Definição por meio da função header(), do PHP:

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

Codificação do banco de dados e das tabelas

Se a sua aplicação usa um banco de dados, ele precisa, também, estar na codificação usada – UTF-8 no nosso caso. Ela é definida quando se criam o banco de dados e as tabelas. Por exemplo, com MySQL, podemos definir as codificação assim:

Codificação do banco de dados:

CREATE DATABASE bancodedados DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

Codificação das tabelas:

CREATE TABLE tabela(
	id SMALLINT(5) UNSIGNED NOT NULL auto_incre3ment,
	nome VARCHAR(20) NOT NULL,
	sobrenome VARCHAR(50) NOT NULL,
	PRIMARY KEY (id)
) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

Assim, todos os campos do tipo string estarão na codificação utf8.

Migrando Dados Não-UTF-8 Para UTF-8

Muitas vezes, precisamos migrar os dados de um banco de dados que não está em UTF-8 para outro que está em UTF-8.

Se apenas fizermos um SELECT em um e um INSERT no outro, erros de codificação vão aparecer para todo lado. É necessário remover os caracteres não-utf-8. E a melhor forma que encontrei para fazer isso é utilizando a seguinte rotina:

$regex = <<<'END'
/
  (
    (?: [\x00-\x7F]               # single-byte sequences   0xxxxxxx
    |   [\xC0-\xDF][\x80-\xBF]    # double-byte sequences   110xxxxx 10xxxxxx
    |   [\xE0-\xEF][\x80-\xBF]{2} # triple-byte sequences   1110xxxx 10xxxxxx * 2
    |   [\xF0-\xF7][\x80-\xBF]{3} # quadruple-byte sequence 11110xxx 10xxxxxx * 3 
    ){1,100}                      # ...one or more times
  )
| ( [\x80-\xBF] )                 # invalid byte in range 10000000 - 10111111
| ( [\xC0-\xFF] )                 # invalid byte in range 11000000 - 11111111
/x
END;
 
function utf8replacer($captures) {
  if ($captures[1] != "") {
    // Valid byte sequence. Return unmodified.
    return $captures[1];
  }
  elseif ($captures[2] != "") {
    // Invalid byte of the form 10xxxxxx.
    // Encode as 11000010 10xxxxxx.
    return "\xC2".$captures[2];
  }
  else {
    // Invalid byte of the form 11xxxxxx.
    // Encode as 11000011 10xxxxxx.
    return "\xC3".chr(ord($captures[3])-64);
  }
}
preg_replace_callback($regex, "utf8replacer", $text);

Esse código eu retirei deste post no StackOverflow.

Problemas persistentes

Se você usava codificações diferentes, e, depois, modificou apenas a codificação do banco de dados, as acentuações, provavelmente, continuarão erradas. Não basta apenas mudar a codificação, nesse caso; será necessário passar os dados para outra tabela, que esteja, inicialmente, na codificação correta. É possível fazer essa transferência de dados por meio de apenas uma consulta. Para MySQWL, por exemplo, é possível usar um INSERT INTO… SELECT.

No meu Guia Gratuito de 15 Dicas e Boas Práticas de PHP falo mais sobre isso. Além dessa, são outras 14 dicas que vão deixar seus sistemas PHP mis estáveis, seguros e eficientes. Clique aqui para baixar o guia gratuito agora mesmo.

Essa e inúmeras outras dicas e técnicas eu abordo com mais detalhes no meu Curso ULTIMATE PHP. Estude PHP desde o básico, de forma 100% prática. Aprenda como se tornar um excelente programador, reconhecido e valorizado. Clique Aqui e Conheça o Curso Agora Mesmo!

 

The following two tabs change content below.
Graduado em Ciência da Computação, pela Universidade Federal do Paraná (UFPR), é desenvolvedor de software desde 2008, com foco em Desenvolvimento Web com PHP.