Vira e mexe existe alguém aparecendo com problemas com apresentação de caracteres por conta de codificação de caracteres errada. Já escrevi sobre Unicode, Códigos e Símbolos Unicode e sobre HTML entities. Mas neste artigo, veremos como utilizar UTF-8 em tudo e nunca mais ver caracteres sendo exibidos errado.
1º Salve o código-fonte em UTF-8
Antes de mais nada, escolha um bom editor de código-fonte, que lhe permita definir qual a codificação utilizada nos arquivos salvos. Normalmente isso fica nas configurações do editor ou nas opções do momento de salvar.
Se você usa editores em modo texto (vi, nano, pico, etc), talvez seja necessário configurar a codificação nas configurações do próprio emulador de terminal de comandos (gnome-terminal, xterm, etc). E também pode ser necessário definir a variável de ambiente LANG com valor "pt_BR.UTF8" no terminal, antes de abrir o editor, como mostrado a seguir:
$ export LANG=pt_BR.UTF8
Observação: alguns editores tem opção de salvar o arquivo com o BOM. Recomenda-se que não salve o arquivo com estes bytes de marcação, pois eles podem causar comportamento inesperado no PHP. Por exemplo, você não vai conseguir chamar funções como header ou utilizar o recurso de namespaces, que obriga que a declaração de namespace seja a primeira coisa no script.
2º Informe ao navegador que você usa UTF-8
Quando um arquivo PHP gera um HTML e é enviado para o navegador, junto com o arquivo vai um cabeçalho (do protocolo HTTP), onde é especificado o tipo de arquivo e a codificação. Caso você não informe ela explicitamente no seu código, o seu servidor HTTP (por exemplo, o Apache) irá enviar tal arquivo com um mime-type padrão (normalmente "text/html") e uma codificação padrão (normalmente "ISO-8859-1").
Para mudar este cabeçalho explicitamente, e informar corretamente o mime-type e a codificação do documento que você está gerando, utilize a função header, passando a diretiva "Content-type", conforme exemplo:
<?php header('Content-Type: text/html; charset=UTF-8'); echo '<html>'; ...
Caso o arquivo seja de outro tipo, basta mudar o mime-type para o tipo correspondente (por exemplo, "text/css", "text/xml", "application/xhtml+xml", etc).
Porém, nem sempre os arquivos são gerados via PHP. Existem HTML estáticos que precisam informar o cabeçalho HTTP com o mime-type e codificação corretos. Neste caso, existe uma alternativa que é usando a tag meta com o atributo "http-equiv" (equivalente HTTP). Com ela, é possível "simular" cabeçalho do HTTP pelo próprio conteúdo do documento HTML. Isso é feito da seguinte forma:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" > ...
No HTML 5, isso foi simplificado:
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8" > ...
Nos arquivos CSS, você pode opcionalmente informar a codificação na primeira linha do arquivo:
@charset "UTF-8"; ...
Caso você utilize XML ou XHTML, lembre-se de informar a codificação UTF-8 no cabeçalho XML:
<?xml version="1.0" encoding="UTF-8" ?> <html> ...
Ao incluir CSS o JS no seu HTML, também é possível especificar o charset destes arquivos:
... <link rel="stylesheet" type="text/css" href="estilo.css" charset="UTF-8" /> <script src="exemplo.js" type="text/javascript" charset="UTF-8" ></script> ...
3º Comunique-se com o BD via UTF-8
Para que as informações sejam trafegadas entre o PHP e o Banco de Dados usando UTF-8, é preciso declarar esta codificação logo que se conecta ao banco. Isso varia de banco para banco, mas vamos ver alguns exemplos comuns:
MySQL (PDO):
$dsn = "mysql:host=localhost;dbname=world;charset=utf8"; $opcoes = array( PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8' ); $pdo = new PDO($dsn, $usuario, $senha, $opcoes); ...
MySQLi:
$mysqli = new mysqli(...);
$mysqli->set_charset('utf8'));
MySQL (funções):
$conexao = mysql_connect(...); mysql_select_db(...); mysql_set_charset('UTF8', $conexao); ...
Observação: as funções de conexão com MySQL estão depreciadas. Prefira usar PDO ou MySQLi.
PostgreSQL (PDO):
$pdo = new PDO(...);
$pdo->query('SET NAMES UNICODE');
...
PostgreSQL (funções):
$conexao = pg_connect(...);
pg_set_client_encoding($conexao, 'UNICODE');
...
4º Crie seu Banco de Dados em UTF-8
Os campos de texto armazenados em bancos de dados também precisam de uma codificação de caracteres. Caso não seja definida no momento que se cria o campo, a codificação é obtida do padrão da tabela ou do bando de dados. Para definir um valor padrão de codificação de um banco de dados, use os comandos:
MySQL:
CREATE DATABASE nome_bd CHARACTER SET UTF8;
PostgreSQL:
CREATE DATABASE nome_bd ENCODING UNICODE;
5º Lembre-se de especificar a codificação UTF-8 onde puder
Algumas funções em PHP recebem como parâmetro a codificação a ser considerada. Algumas das mais importantes que devem ser ressaltadas são: htmlentities e htmlspecialchars.
Além disso, ao realizar operações com expressões regulares PCRE, lembre-se de utilizar o modificador "u" ao final da expressão, indicando que ela é UTF-8, conforme o exemplo:
preg_match('/^[a-z](.*)/u', $str, $matches);
Um conjunto importante de funções, leva em consideração a localidade (com uma codificação) para funcionar. Então, também é importante definir a localidade adequadamente com a localidade UTF-8:
setlocale(LC_ALL, 'pt_BR.utf8');
Lembre-se que a localidade depende do servidor e o nome utilizado pode variar.
A partir do PHP 5.3, é possível especificar a codificação de um arquivo PHP com uma chamada declare logo no início do arquivo PHP:
<?php declare(encoding='UTF-8'); ...
Conclusão
Tomando as devidas medidas, é possível utilizar UTF-8 sem grandes problemas em todas as camadas do seu sistema: no HTML, no PHP e no Banco de Dados. Erro de codificação? Nunca mais!
110 comentários
Letras pequenas no menu parecem propagandas.
Muitas artigos interessantes no seu blog.
Parabéns!!!11!
Obrigado, xico.
As letras pequenas são aquelas abaixo do título do blog? Realmente imaginei que poderiam parecer propaganda, mas, de qualquer forma, são apenas âncoras para itens da barra lateral.
Concordo plenamente com você, num adianta fazer uma salada de codificação e depois tentar corrigir com (funções), o negocio tem de vir padronizado da raiz. mais é isso ai..
Meus parabéns seus artigos são ótimos, sempre acrescentam algo.
Abraço
Cara, e os arquivos xslt?!
eu tenho um arquivo xsl codificado com utf8.
usado por um xml que tbem eh utf8.
mas ele acusa erro qndo encontra um caracter com acento (estando esse caracter no arquivo xsl).
Tem alguma dica?!
Olá Anônimo.
Se você salvar os dois arquivos em UTF-8 e declalar que são UTF-8 (no cabeçalho do arquivo XML e do XSLT), provavelmente vai dar certo. É só usar o atributo "encoding".
Fiz um exemplo rápido aqui e funcionou. Se quiser, mando para você ver.
Amigo, estou com um probleminha..
Tentei passar meu código para vc da uma olha mais não é aceito códigos de programação.
Não faz sentido, pois o blog é de programação web.
Olá, Anônimo,
Infelizmente o blogger é uma plataforma compartilhada para vários blogs, por isso ele não permite inclusão de código. Porém, se você quiser, pode colocar o código em algum site próprio para isso como o pastebin.com e depois indicar o link com a pergunta aqui nos comentários.
bah, q luz foi esse artigo; sempre combati o utf-8 achando que isso era charset de gringo e nunca refleti realmente; eu saia setando locale latin1 e iso-8859-1 em tudo q podia (plataforma, so, php, mysql); sendo ainda mais sincero me considerava o máximo q configurava um editor de texto com apenas um caracter para quebra de linha. Ainda, notava q a codificação utf-8 numa folha de estilos aceitava + símbolos do q uma em iso-8859-1. Minha humilde contribuição a este artigo: acrescentar na primeira linha da folha de estilo '@charset "utf-8";' pra indicar a codificação... parabéns pelo blog
Sei que ja faz um tempo esse post mas tenho uma duvida, como faço:
$conexao = mysql_connect(...);
mysql_select_db(...);
mysql_set_charset('UTF8', $conexao);
no doctrine?
se alguém souber e puder ajudar agradeço.
Parabens!
Muito bom, ótimo conteúdo, bem explicado e otimos exemplos
Valeu!
ainda estou me acustumando com o uso do utf-8 porem é a codificação padrão em todo mundo, assim sendo se você vai desenvolver um sistema nôvo salve os cod fontes em utf8 pra depois não ficar semanas ou mais como eu fiquei para converter do latin para utf.
Rubens, obrigado pela ajuda!
Resolveu meu problema por aqui.
Muito bom o texto!
Abraço,
Paulo
Muito obrigado pelos posts! Eles hoje me adiantaram e muito em alguns problemas que estava quebrando a cabeça pra resolver!
Poderia da uma luz?
Uso a conexão dessa maneira.
setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e){
echo $e->getMessage();
exit(" Erro ao conectar.");
}
?>
na página o html está tudo certo nas no db sai aqueles acaracteres estranhos no lugar da acentuação..
Grato.
Olá, Anônimo
Talvez você esteja visualizando o BD de forma incorreta. Ao conectar no MySQL via terminal, por exemplo, você precisa executar o comando:
mysql> SET NAMES utf8;
Além disso, precisa garantir que o terminal esteja exibindo em UTF-8 também.
No Charset já tive muitos problemas com ele, porque antigamente utilizava o ISO-8859-1, hoje com o novo UTF-8 eu posso utiliza-lo, a Solução que eu encontrei foi adicionar uma chatset diretamento no .htaccess e manter o padrão de definição em todo o projeto.
Tive problemas com strtoupper com os caracteres especiais, para o caso de alguém também ter o mesmo problema, podem ser usadas as funções mbstring do PHP (http://php.net/manual/en/book.mbstring.php). No caso do strtoupper, a sintaxe é mb_strtoupper($string, 'UTF-8').
Para habilitar no Windows (PHP 5.4) é só descomentar a linha extension=php_mbstring.dll no php.ini. Acredito que no Linux o procedimento seja similar.
Luiz:
Obrigado pelas dicas!
Segui sua orientação passei tudo pra UTF-8, tive de trocar meu editor de texto que nao escrevia em (UTF-8 sem BOM), mas agora esta tudo melhor. :)
Obrigado pelo artigo. Sucesso!
Olá,
Eu tenho um código que faz a conexão no mysql por javascript. Como faço para comunicar com o BD em utf-8?
Segue o código:
ConectaBase();
}
// Conexao com banco
function ConectaBase()
{
$this->link = @mysql_pconnect( $this->servidor, $this->usuario, $this->senha);
if (!$this->link) {
die("Error na conexao: ".mysql_error()." - ".mysql_errno());
} elseif (!mysql_select_db($this->banco, $this->link)) {
die("Error na conexao: ".mysql_error()." - ".mysql_errno());
//mysql_errno(): numero do erro
//mysql_error(): descrição do erro
}
}
// Execução da query
function sql($query)
{
$this->query = $query;
//echo $this->query;
if ($result = mysql_query($this->query,$this->link)) {
return $result;
mysql_free_result($result);
} else {
return 0;
}
}
function tabelas()
{
if ($result = mysql_list_tables($this->banco)) {
return $result;
} else {
return 0;
}
}
}
?>
Obrigado!
Bernardo, este código que passou é PHP, não JavaScript.
Sobre a sua pergunta, para se comunicar com o BD em UTF-8, leia atentamente a sessão "3º Comunique-se com o BD via UTF-8" neste post, que lá estará a resposta.
Aproveito para alertá-lo de que as funções de conexão com MySQL já estão depreciadas. Se possível, utilize PDO ou MySQLi. Tem um artigo aqui no blog sobre PDO:
http://rubsphp.blogspot.com.br/2010/09/pdo.html
Olá Rubens,
Obrigado pela resposta.
Eu consegui fazer o mysql puxar as informações em utf-8!
O problema agora está só na parte do HTML, que continua mostrando os acentos com símbolos.
No php.ini está setado default_charset = "UTF-8".
Eu inclui no index.php do meu site:
header('Content-Type: text/html; charset=UTF-8');
e
Mas ele continua mostrando tudo com símbolos.
Sabe o que pode ser?
Obrigado!
Olá, Bernardo
Pelo visto, você já fez tudo certo. Sugiro que faça um teste: consulte um registro do seu BD que contenha algum acento. Depois, no PHP, imprima o tamanho da string. Se o número for maior que a quantidade real de símbolos, provavelmente está chegando UTF-8 mesmo (então o problema está na exibição pelo navegador). Se a quantidade for igual a de símbolos, provavelmente você está obtendo o conteúdo em ISO-8859-1.
Sugiro a leitura deste outro artigo para saber exatamente o que é o UTF-8, Unicode, ISO-8859-1, codificação de caracteres, etc:
http://rubsphp.blogspot.com.br/2010/10/unicode.html
Como faz a declaração do UTF-8 em um PDO para Sql Server? Alguéem??
Mariane, creio que este link tenha a resposta:
http://msdn.microsoft.com/en-us/library/ms191200.aspx
Você precisa criar os campos do BD com os tipos nchar, nvarchar e ntext (ao invés de char, varchar e text).
Não sei dizer se precisa de algum tratamento especial no lado do PHP, pois nunca usei o Sql Server.
Como converto latim em UTF-8?
Anônimo, a função "utf8_decode" converte de UTF-8 para ISO-8859-1.
Muito bom Rubens, gostaria de colocar aqui uma experiência que tive que me arrancou os cabelos.Eu trazia o conteúdo de um formulário para inserir no banco. Tudo já estava em UTF-8, á página, o Database as tabelas e os campos, e visualizava corretamente, com acento. Porém ao incluir no banco apareciam caracteres estranhos. A solução foi usar isso --->mysql_query("SET NAMES 'utf8'");
mysql_query('SET character_set_connection=utf8');
mysql_query('SET character_set_client=utf8');
mysql_query('SET character_set_results=utf8');
Dessa forma a variável acentuada foi inserida no banco corretamente e com acento. É isso...
Olá Mauro,
Obrigado por compartilhar. Embora eu ache estranho não ter funcionado com o que você diz ter usado. Talvez você pode ter se enganado no momento da verificação.
A documentação do PHP diz que a forma ideal de informar o charset de comunicação com o BD (usando a biblioteca de funções do MySQL) é com a função mysql_set_charset:
http://www.php.net/manual/en/function.mysql-set-charset.php
Neste link diz que deve-se dar preferência à função ao invés de usar a query "SET NAMES".
Note que quando você vai conferir o dado no MySQL usando um cliente no terminal, também precisa informar o charset:
$ mysql --default-character-set=utf8 ...
A forma mais simples que eu vejo de detectar se o banco está armazenando utf8 ou latin1 é inserindo um campo texto com valor "ç". Depois, faço a consulta:
SELECT LENGTH(campo) FROM tabela;
Se a consulta retornar "1", significa que está em latin1 (1 byte), e se retornar "2" significa que está em utf8 (2 bytes).
Mais detalhes sobre o UTF-8 estão no link: http://rubsphp.blogspot.com/2010/10/unicode.html
Exatamente, essa diretiva --> mysql_set_charset('utf8'); substitui a query "SET NAMES" com êxito. Valeu Rubens, grande abraço...
Boa tarde Rubens! Ótimo post. Mas estou com o seguinte problema. Quando salvo caracteres acentuados no banco, eles ficam salvos todo errado. E quando recupero caracteres acentuados no banco, que eu inseri diretamente pelo SGBD eles sao exibidos todos errados também. Estou utilizando o zendserver e conecto ao SQL server pelo pdo_mssql. Tenho que utilizar o ISO-8859-1. Você sabe o que pode estar acontecendo de errado?
Olá, Marco Túlio
Se você conecta diretamente ao SGBD, precisa garantir que está trafegando os dados na codificação correta. Não conheço de mssql, mas no MySQL, por exemplo, precisa ajustar o terminal para usar ISO-8859-1 e executar "SET NAMES latin1" assim que se conecta.
Gostei muito, mas faltou mencionar o SQLite...
Parabéns pelo teor das informações
Rubens, parabéns pelo blog, esta excelente. Referente a UTF-8 tenho uma dúvida, vejamos se consegue me ajudar, em um site que montei, os links criados, funcionam perfeitamente, porem na URL, leva por %20 ao invés do espaço, e isto não contribui para as estatísticas dos sites de pesquisa, de forma que eu iria trocar por '-', como imagino que quem esteja postando o %20, seja o CHARSET, pergunto, se você teria alguma ideia para que isto não ocorresse.
Olá, Anônimo
As URLs utilizam um outro tipo de codificação para os caracteres especiais. As funções para codificar e decodificar valores em uma url são: "urlencode" e "urldecode". Além delas, talvez seja útil você conhecer a função http_build_query. Veja este artigo para entender:
http://rubsphp.blogspot.com.br/2012/04/manipulacao-de-url-uri-e-links.html
A questão de utilização do "-" é útil se você está querendo montar URLs amigáveis. O Google recomenda o uso do "-" para separar palavras na URL, em oposição ao "_" (underscore). Veja as recomendações que ele faz neste link:
https://support.google.com/webmasters/answer/76329
Quando se trabalhar com URLs amigáveis ao invés de utilizar query string (parâmetros na URL, colocados após o símbolo "?"), é preciso tomar alguns cuidados:
* se você pretende distinguir o símbolo de hífen dos símbolos de espaço.
* se você pretende usar símbolos especiais para URLs, como "&", "?", ":", "@" e "/".
Maravilhoso!1, Melhor conteúdo! vlw
Ola Rubens excelente artigo e veja configurando o configbd ou a conexao como vc demonstra -
$dsn = "mysql:host=localhost;dbname=world;charset=utf8";
$opcoes = array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8'
);
$pdo = new PDO($dsn, $usuario, $senha, $opcoes);
realmente ja inseriu no banco com acento e no internet explorer ele é visualizado com acento,porém no google chrome aparecem simbolos - como resolvo isto, haja visto que a pagina que retorna dados no INTERNET EXPLORER DEMONSTRA COM ACENTUAÇÃO COMO A TABLE DO BD JA NO GOOGLE CHROME NÃO - COMO RESOLVERIA ISTO - FICO NO AGUARDO E DESDE JA AGRADEÇO
Ola Rubens excelente artigo e veja configurando o configbd ou a conexao como vc demonstra -
$dsn = "mysql:host=localhost;dbname=world;charset=utf8";
$opcoes = array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8'
);
$pdo = new PDO($dsn, $usuario, $senha, $opcoes);
realmente ja inseriu no banco com acento e no internet explorer ele é visualizado com acento,porém no google chrome aparecem simbolos - como resolvo isto, haja visto que a pagina que retorna dados no INTERNET EXPLORER DEMONSTRA COM ACENTUAÇÃO COMO A TABLE DO BD JA NO GOOGLE CHROME NÃO - COMO RESOLVERIA ISTO - FICO NO AGUARDO E DESDE JA AGRADEÇO
Olá, avdvdfotosefilmagens
Aparentemente isso que você citou é resolvido com o item 2 do artigo, ou seja, informar ao navegador que o conteúdo apresentado tem codificação UTF-8.
Olá Rubens primeiramente obrigado - bem eu já tinha feito isto - o que ocorre - O HTML e os campos da base já estão gravando acentuados veja como está setada a minha base de dados em relação ao collation e caracter set
+ Opções
Variable_name
Value
character_set_client
utf8
character_set_connection
utf8
character_set_database
utf8
character_set_filesystem
binary
character_set_results
utf8
character_set_server
latin1
character_set_system
utf8
character_sets_dir
/usr/share/mysql/charsets/
na base os campos já estão sendo salvos na minha table acentuados
mas na hora de mostrar na pagina de teste agora tb no internet explorer alem do google - aparece desta forma - a primeira linha é a do html da pagina a segunda em diante é o retorno de dados do banco de dados
no google chrome aparece desta forma
Produto, Marca (Nome do anunciante) Ação
sampa, S�o Paulo (S�o Paulo) Enviar e-mail para pgto Alterar Excluir
sampa, S�o Paulo (S�o Paulo) Enviar e-mail para pgto Alterar Excluir
sampa, S�o Paulo (S�o Paulo) Enviar e-mail para pgto Alterar Excluir
sampa, S�o Paulo (S�o Paulo) Enviar e-mail para pgto Alterar Excluir
sampa, S�o Paulo (S�o Paulo) Enviar e-mail para pgto Alterar Excluir
no internet explorer desta forma
Produto, Marca (Nome do anunciante)
Ação
sampa, S�o Paulo (S�o Paulo)
mas agora consegui resolver o problema mudando as linhas do header da pagina e no include colocando o include correto e alterando toda a base de dados para utf8-generalci
header da pagina
'SET NAMES UTF8'
);
$conn = new PDO($dsn, $usuario_banco, $senha_banco, $opcoes);
agora o novo resultado no internet explorer e google chrome
google
Produto, Marca (Nome do anunciante) Ação
sampa, São Paulo (São Paulo) Enviar e-mail para pgto Alterar Excluir
sampa, São Paulo (São Paulo) Enviar e-mail para pgto Alterar Excluir
sampa, São Paulo (São Paulo) Enviar e-mail para pgto Alterar Excluir
sampa, São Paulo (São Paulo) Enviar e-mail para pgto Alterar Excluir
sampa, São Paulo (São Paulo) Enviar e-mail para pgto Alterar Excluir
internet explorer
Produto, Marca (Nome do anunciante)
Ação
sampa, São Paulo (São Paulo)
sampa, São Paulo (São Paulo)
sampa, São Paulo (São Paulo)
sampa, São Paulo (São Paulo)
sampa, São Paulo (São Paulo)
obrigado desde ja pela ajuda e espero tb ter compartilhado esta mesma ajuda e este lance da acentuação para os colegas
detalhe - tb solicitei ao meu provedor host - mudar de latin1 para utf-8 general ci a seguinte linha do server do bd -
Variable_name
Value
character_set_client
utf8
character_set_connection
utf8
character_set_database
utf8 // esta linha antes no provedor cpanel estava como Latin1 e pos solicitacao foi para utf8
character_set_filesystem
binary
character_set_results
utf8
character_set_server
latin1
character_set_system
utf8
character_sets_dir
/usr/share/mysql/charsets/
para verificar estas linhas no SQL DA BASE NO PHPMYADMIN EXECUTAR ESTE COMANDO SQL
SHOW VARIABLES LIKE '%char%';
obrigado á todos e desde já agradeço
Tutorial fantástico!
Obrigado, cara! Me ajudou muito! Parabéns pelo site! Felicidades a você!!! Muito obrigado!
Agradeço os elogios. Aliás, Joaquim, vi seu site e achei muito bonito suas obras de arte. Também sou entusiasta de arte realista, mas fico só no desenho como hobby.
Muito bacana!
Haveria alguma forma simplificada de converter todo o banco para UTF-8? Estou administrando um que foi criado em Latin 1.
Obrigado.
Olá, Guilherme
Creio que não exista algo tão direto pra fazer isso. Veja um tutorial que explica como fazer isso:
http://docs.moodle.org/23/en/Converting_your_MySQL_database_to_UTF8
VALEWWW DEMAIS!!! QUEBROU UM GALHÃO
Legal, mas... vejam a seguinte query:
SELECT * FROM Pessoa WHERE nome LIKE '%Assunção%'
Essa query em LATIN1, ou WIN-1252, casa com qualquer nome que contenha 'Assuncao', 'Assunçao', 'Assuncão' e 'Assunção'.
Mas em UNICODE ou UTF-8 só casa com nomes que contenha exatamente o termo 'Assunção'.
E isso faz toda a diferença numa tela de busca de cliente, por exemplo. Esse é um dos motivos porquê ainda não abandonei o LATIN1 no Banco de Dados.
Se alguém souber como fazer a mesma coisa em UNICODE, me avise...
Olá, Anônimo
Acabei de fazer um teste aqui, montando uma tabela em UTF8 e consultando um termo com acento. Funcionou perfeitamente.
Talvez você tenha feito algo errado. Experimente acessar o client de MySQL e executar este exemplo:
SET NAMES utf8;
CREATE DATABASE teste DEFAULT CHARACTER SET utf8;
USE teste;
CREATE TABLE usuarios (nome VARCHAR(128)) CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO usuarios VALUES ('assuncao'), ('assunçao'), ('assunção');
SELECT nome FROM usuarios;
Refiz o teste, e realmente, funciona no MySQL. Mas...
Não funfou no MSSQL e no SQLite, então, testem bem no SGBD do projeto antes de implementar, pra não dar zica.
No comentário anterior, eu joguei essa questão baseado numa experiência feita com MSSQL, onde tínhamos que buscar dados em webservices UTF-8, e o banco era WIN-1252. Pensa no sofrimento para conversão de charset.
A dica é válida: SEMPRE que puderem, usem UNICODE.
Simplesmente incrível esse post, explicou de uma vez por todas as melhores maneiras de fazer com que o sistema não nos dê surpresas na hora de ir para o ar! Obrigado e parabéns!
Muito bom! Me salvou!!!
Nobre amigo:
1) Fiz exatamente o que indicou. UTF-8 para todo mundo;
2) Meu banco no MySQL estava LATIN1, aproveitei e converti para UTF-8 alterando em propriedades.
3) Percebi que os meus arquivos eram gerados no formato ANSI. Converti-os para UTF-8 também.
Um SELECT está trazendo quadradinhos em vez dos caracteres especiais ou acentuados.
Porque será?
Olá, Anônimo
Experimente inserir um registro com acento, consultá-lo e ver se é exibido corretamente. Se for, é provável que o erro foi durante a conversão do banco. Neste artigo mostra como fazer:
http://blogs.law.harvard.edu/djcp/2010/01/convert-mysql-database-from-latin1-to-utf8-the-right-way/
Olá Rubens, gostaria de tua ajuda, se estiver ao teu alcance. Eu usava o php com iso-8859-1 e com ele gravava imagens acentuadas num servidor brasileiro e funconava tudo ok. Migrei de servidor, para um servidor inglês, onde me falaram que usam o utf-8 e o servidor deles não reconhece o iso-8859-1, as imagens não abrem mais nos sites, da erro por causa dos acentos, vou ter que enviar as milhares de imagens que tenho, tudo de novo sem acento ? ou tem alguma solução ?
Olá, Anônimo
Explique melhor essa situação. São imagens estáticas ou imagens dinâmicas geradas pelo PHP sob demanda? (utilizando a biblioteca GD ou outra do gênero)
Demais seu post! Resolvi meu problema com o passo 3 !!
prezado
estou com um problema no zend. faço as consultas no banco de dados e até a classe do form tudo é mostrado ok, mas quando envio para o zend enviar para o browser, desta forma: $this->addElement('Select', 'Category',array(
'label' => 'Região de origem:',
'AutoComplete'=> true,
'MultiOptions' => $this->_paramregiao,
'required' => false ));
o multioptions quando o array tem acentos, ele não reconhece os caracteres, aparece por exemplo aná,polis para simbolizar anápolis. o engraçado é que o label "Região de origem" aparece ok.
Olá, Anônimo
Creio que você já esteja passando as strings codificadas com entities HTML. Daí o zend codifica algo que já está codificado, e acaba exibindo as entities literalmente. Verifique a origem do seu array de opções e confira que lá as strings já estão codificadas.
obrigado Rubens
Não resolveu mas o problema mudou. antes trocava os caracteres pelos nomes das entidades. eu estava codificando um json com htmlentites, realmente. tirei o htmlentities e aí fiz apenas $sRetorno = json_encode($arr). aí simplesmente trunca. por exemplo onde é Goiânia, fica Go.
digo, onde é Goiânia fica Goi
olá Rubens
na verdade resolveu. tinha outras funções antes que estavam atrapalhando. fiz a decodificação e deu certo. muito obrigado.
Bem legal mesmo. Mas como eu faço com os javascript, tanto os que estão com os códigos na própria página como também aqueles que são chamados via src, tipo:
script src="caminho/nomearquivo.js" /script /head - Eles também precisam ser salvos como utf8?
Sim, JavaScript também podem ser salvos em UTF-8. Tanto os da página quanto os externos.
Até onde entendi, convém salvar o html(php), css e js com codificação UTF8 sem BOM, pois eu tinha feito tudo no Bloco de Notas e salvo em UTF8, porem o Scrubtheweb deu aviso de erro pois estava com BOM. então:
Salvar todos no Notepad++ "Codificação em UTF8 (Sem BOM)".
Fiz isso até com o htaccess, mas deu zebra. Lá tem que ser ANSI mesmo.
Por favor, se eu estiver errado me corrija.
Desde já muito obrigado e parabéns pela iniciativa.
Walter
Olá, Walter
Creio que esteja tudo certo. De fato, o BOM é problemático, pois é considerado código indevidamente.
Quanto ao htaccess, creio que também possa ser salvo como UTF-8. Qual o problema que você teve?
Bloqueou o site, tanto para os motores de busca como para o acesso normal. Então assim que eu percebi rapidinho voltei para ANSI. Pode ser que eu tenha errado alguma coisa.
Walter.
Boa noite Rubens,
Estou com um problema desses, já fiz muitos testes e não consigo resolver.
Quando gravo uma tabela, os caracteres com acentos são gravados acrescidos daqueles caracteres "estranhos". Por exemplo, "Ações" fica gravado na tabela como "Ações".
Ao acessar a tabela para mostrar essas informações não ocorrem problemas, Os problemas ocorrem na inserção ou alteração pois, pelo fato de acrescentar caracteres, ultrapassa o tamenho definido para o campo da tabela dando erro.
Meu HTML:
!DOCTYPE html
html lang="pt-BR"
head
meta charset="utf-8"
Meu Banco de Dados:
Postgres 9.3.2
Encoding UTF8
Collation Portuguese_Brazil.1252
Character type Portuguese_Brazil.1252
Minha conexão com BD:
$this->objPDO = new \PDO($dsn, $user, $pass);
$this->objPDO->query('SET NAMES UNICODE');
Podendo me ajudar agradeço muito.
Obrigado,
Athos
No meu comentário anteriror a palavra Ações que deveria aparecer com erro, do exemplo, acabou aparecendo escrita de forma correta.
Na tabela ela fica errada. Fica dessa forma, sem os espaços em branco que digitei aqui para poderem aparecer:
A & cedi l ; &o tild e ; es
Athos
Olá, Athos Rafael
Não entendi direito. Você diz que está inserindo errado, mas por onde você viu os dados? Se foi consultando os dados e exibindo no HTML, você precisa se certificar que a página esteja sendo exibida em UTF-8 também (passo 2 do artigo).
De fato, a codificação UTF-8 exige mais bytes do que ISO-8859-1 para armazenar alguns símbolos. Para entender detalhes sobre o unicode, recomendo que veja o artigo:
http://rubsphp.blogspot.com.br/2010/10/entendendo-o-unicode-utf8.html
Para depurar, veja o tamanho do texto antes de inserí-lo no banco (use a função strlen). A palavra "Ação" precisa retornar tamanho 6 para ser UTF-8. Se retornar 4 é porque está em outra codificação. O mesmo vale na hora da consulta.
Rubens,
Obrigado pelo retorno.
Vejo os dados na opção view da tabela no pgAdmin3 e também num log que gravo num arquivo txt.
Mas hoje, pela manhã, descobri o problema. Ao obter os dados do $_POST executo htmlentities.
Trata-se de um bug do PHP 5 na utilização do htmlentities. Bastou retirá-lo que funcionou.
Seguem uns links:
http://www.simplemachines.org/community/index.php?topic=497799.0
https://wiki.php.net/rfc/default_encoding
Agora o problema é como fazer para não deixar de usar o htmlentities ou atualizar a versão para o PHP 5.6 e verificar se está mesmo resolvido o bug.
Obrigado,
Athos
Nossa mano, tentei em tudo que é site resolver um problema q eu tava tendo com charset!! Fazia tudo o que era pedido, nada resolvia!! Até que adicionei uma única linha de código, que faltava e encontrei nesse site, a utilização do mysql_set_charset('UTF8', $conexao); e aí funcionou! Já tava perdendo os cabelos cara, muito obrigadoooo mesmooooo!!!!!!!!
Valeu mesmo, problema resolvido. Parabéns por compartilhar seu conhecimento.
Como declarar o Charset no CSS ?
tentando mudar
.tovar_sale {position:relative;}
.tovar_sale:before {
content:'Sale';
para
.tovar_sale {position:relative;}
.tovar_sale:before {
content:'PROMOÇÃO'; Quebra a codificaçao css e o layout do site
A Torres, informe na primeira linha do arquivo CSS:
@charset "UTF-8";
Bom dia Rubens,
Fazem dias que estou tentando resolver esse problema de caracteres. Tenho um form no site que chega perfeito, mas o do contato que é básico não. Preciso de ajuda... fazem 3 dias que estou em cima disso somente...
O código é o send-email.php que está abaixo. No html está contato.html está tudo certo também, com o
meta charset="utf-8" no cabeçalho.
Ver codigo:
http://pastebin.com/DwL064DX
O que está errado?
Preciso fazer um .htacess? O que está invalidando o envio deste form codificado em UTF8?
Desde já agradeço muito,
Marcos
Olá, Marcos
Segue o link com algumas correções que encontrei:
http://pastebin.com/XhyrFRpp
Os erros que vi foram estes:
* A expressão regular precisa do modificador "u" para tratar caracteres em UTF-8 (linha 34);
* O assunto do e-mail precisa ser codificado de acordo com a RFC 2047 http://www.faqs.org/rfcs/rfc2047.html (linha 89);
* O tipo de conteúdo enviado no e-mail precisa ser especificado, juntamente com seu charset (linha 90);
* As diretivas "From" e "Reply-To" são do protocolo HTTP e não podem ser traduzidas (linhas 91 e 92).
O ideal é utilizar alguma classe para abstrair o processo de envio de e-mail, pois existem vários detalhes para serem tratados. Uma sugestão: use o phpmailer.
Rubens....
Não sei como lhe agradecer.
Seus conhecimentos foram um bálsamo e tudo simplesmente funciona.
Realmente, estou profundamente agradecido, e inspirado, por ter recebido uma ajuda tão fundamental de alguém que não conheço pessoalmente.
MUITO OBRIGADO!
Abs!
Eu estou com um problema parecido, mais no meu caso eu preciso inverte!!
Eu preciso que o texto apareça assim: Hércules
E esta aparecendo assim: Hércules
Alguem sabe me ajudar?
Olá, Karl
Em que situação você precisa exibir o texto desta forma?
Para fazer isso numa página é relativamente simples: você salva um arquivo HTML com o texto "Hércules" e salva em UTF-8, mas indica que a página é ISO-8859-1. Veja o 2º item do artigo, mas troque a codificação por ISO-8859-1.
Para mais detalhes, recomendo que leia este artigo:
http://rubsphp.blogspot.com.br/2010/10/entendendo-o-unicode-utf8.html
Excelente artigo!! Me ajudou bastante!
Excelente checklist! Me ajudou muito!
Olá Rubens. Obrigado por compartilhar conosco seu conhecimento, porém atualmente aqui na empresa estamos passando por um obstáculo do qual não estamos conseguindo uma solução.
Estamos com um projeto do qual já constava em uma determinada tabela dados cadastrados em utf-8 e iso-8859-1. Quando aparece no site, os caracteres ficam dessa forma Can��o ou Canção. Já usamos o utf8_encode() e o utf8_decode() do PHP, porém algumas palavras tem solução e outras não.
Já usamos também a própria codificação do HTML, mas nada resolveu. Pensamos em fazer manualmente, porém só nessa tabela, tem mais de 30 mil registros.
Como poderíamos agir nesse caso?
Desde já agradecemos muito pela ajuda.
Olá, José Marcos
Veja este artigo:
http://rubsphp.blogspot.com.br/2012/08/convertendo-iso88591-para-utf8-de-forma-segura.html
Lá eu coloquei uma função que converte ISO-8859-1 para UTF-8, mas o que já está em UTF-8 é mantido. Ela será útil se um mesmo texto tiver caracteres ISO-8859-1 e UTF-8.
Caso existam alguns registros em ISO e outros em UTF-8, você pode converter os registros que são ISO-8859-1 para UTF-8 checando primeiro se ele não é UTF-8, desta forma:
if (!preg_match('/./u', $texto)) {
$texto = utf8_encode($texto);
}
E então salvando o texto final no BD, para ficar tudo UTF-8.
Bom dia Rubens. Estaremos implantando a sua função em nosso projeto e colocando os créditos para o seu blog.
Muito obrigado pela ajuda.
Um abraço.
Parabéns pelo seu blog, resolveu um problema que estava tendo com PHP, continue assim..
SALVOU MEU PROJETO PARARBENS
Muito Obrigado resolveu todos os meus problemas, belo post.
Muito obrigado meu amigo. Perfeita sua explicação. Agora entendi. No meu caso solucionou apenas modificando o arquivo de conexão com o banco.
Sucesso!!!
Você tem o dom.
Preciso de sua dica...Instalei um script no hostinger e estou lutando para corrigir a codificação ...http://www.simuladodeconcurso.com.br/simulado
quando importo o BD e visualizo no phpMyadmin está tudo correto , na colação ele vem original como latin1, alterei para utf8 e mesmo assim continua com problema na acentuação ...como devo proceder??? Obrigado.
Notei que na página
http://www.simuladodeconcurso.com.br/simulado
que você citou, está codificado utf8 mas você fêz algumas codificações de caracteres em algumas palavras.
Eu acho que uma vez que você codificou utf8 não precisa codificar mais nada. Use a acentuação normal do teclado e seja feliz.
Eu uso php mysql e tentando usar uma lib criada para exibir os registro me deparei com esse problema, após tentar resolve-lo de todas as formas propostas, sem exito para essa lib, voltei a minha forma de trabalhar com isso! somente para complementar o post do seu blog que foi muito útil (li todos os comentário na esperança de achar o que precisava):
-->>
$link = mysql_connect("meuservidor", "meuusuario", "minhasenha");
mysql_select_db(bd", $link);
$result = mysql_query("SELECT * FROM tabela", $link);
$num_rows = mysql_num_rows($result);
echo "Exibindo $num_rows Registro(s)\n";
echo "Profissionais em Atendimento:"; ?>
echo "br>"; ?>
$con = mysql_connect('meuservidor', 'meuusuario', 'minhasenha') or
die('Não foi possível conectar');
@mysql_query("SET CHARACTER SET 'utf8'", $con);
mysql_select_db("bd", $con);
$result = mysql_query('SELECT * FROM tabela');
while($row = mysql_fetch_array($result)){
echo 't border="0">';echo 'tr>';echo 'td>';
echo $row['campo1'];
echo ' - ';
echo $row['campo2'];
echo ' - ';
echo $row['campo3'];
echo ' - ';
echo $row['data'];
echo "br />";
echo 'td>';echo 'tr>';echo 'tag';echo 'r>r>';
}
mysql_close($con);
com isso tenho o número de registros gravados na tabela e os dados aparecem corretamente na página.
Exibindo 11 Registro(s)
...manipulação de fármacos, produção. etc.
o outro código é esse: (não funcionou)
xmlns="http://www.w3.org/1999/xhtml" lang="pt-br" xml:lang="pt-br"
header('SET NAMES UTF8');
echo 'tml>';
//eta http-equiv="Content-Type" content="text/html; charset=utf-8" />
//echo 'tml>';
// seleciona o grupo de caracteres utilizados na pagina
ini_set('default_charset','utf8');
require ("../Process.php");
$p = new Process();
require ("../T ab le.php");
$table = new Table ( $p-> RecoverHeader("Select * tabela") ,$p-> RecoverInfos("Select * from tabela"));
@mysql_query("SET CHARACTER SET 'utf8'", $this);
$ta ble ->setLink("favicon.ico");
$ta ble ->mount();
// seu código que usei para ver se funcionava
function sanitizar_utf8($texto) {
$saida = '';
$i = 0;
... }
}
return $saida;
}..
link rel = "stylesheet" href="../estilos/GraphicsStyles.css" >
mas aqui o resultado ainda é esse: "produ��o"
se puder ajudar ou precisar de mais detalhes do projeto é só falar, abraços
DEU CERTO, OBRIGADO! JÁ ESTAVA LOUCO COM ESTE PROBLEMA, E ENCONTREI A SOLUÇÃO AQUI!
OBRIGADO!
Excelente artigo. Me ajudou demais!!!! Parabéns!
Qual é a codificação padrão, caso eu não indique que é UTF-8?
Vinícius, depende. Cada software pode optar por ter alguma codificação padrão ou nem mesmo aceitar codificações diversas (aceitando apenas alguma específica). Porém, UTF-8 tem se tornado a mais comum para ser a padrão.
Estava com problema do Json retornando null com caracteres especiais e seu exemplo MySQL (PDO) funcionou perfeito. Muito bom
Fiz questão de comentar KKK TOP! muito bom! eu já estava aqui impaciente e já tinha adicionado UTF-8 no cabeçalho mas ainda não tinha definido na classe de conexão com o banco...
ótimo!
Boa tarde! Amigo poderia me dar uma ajuda urgente? Tenho uma loja virtual de oscommerce e o db está todo em utf-8, o site todo em utf-8. Mas quando adiciono os nomes às categorias, ele gera o link pras categorias com acentuação, o que, claro, faz dar errado no browser. Como transformar as palavras em palavras sem acento para os links? Obrigada, desculpe o incômodo! E parabésn pelas ótimas matérias! Lucy
Oi, Lucy
Em teoria, as URIs são UTF-8, portanto não é problema a URL ter acentos.
Em todo caso, dê uma olhada na função iconv:
setlocale(LC_CTYPE, 'pt_BR.UTF8');
$texto = iconv('UTF-8', 'ASCII//TRANSLIT', 'texto com áçêñtõ');
var_dump($texto);
Vou fazer os testes aqui, muito obrigada pela ajuda! Abraço! ~Lucy
Funcionou aqui, grato.
Valeu! Me salvou!
Muito interessante, me ajudou muito. Parabéns!
Opa!
Depois de quebrar a cabeça, consegui corrigir a bagaça!
Já havia feito tudo que tem na net: banco UTF-8 general-ci, arquivo com formato utf8, colocar no header o , colocar aqueles baratos de mysql_query("SET NAMES 'utf8'")...
e mesmo assim nada!
então li teu post e adicionei à minha conexão a expressão: $this->mysqli->set_charset('utf8');
BINGO!!!
valew!!
Valew d+++
Deu super certo!!!!
vlw ajudou muito
Tive esse problema desde a semana passada, consegui resolver criando um arquivo com o nome de paginacao.cgi contendo o seguinte, e os acentos funcionaram.
#!/bin/sh
Content-type: text/html
Language: pt-br
Charset: UTF-8-pt-br
Parabéns, artigo excelente...
Resolveu meu problema com a codificação charset indicada no tópico "Ao incluir CSS o JS no seu HTML, também é possível especificar o charset destes arquivos:".
Postar um comentário
Nota: fique a vontade para expressar o que achou deste artigo ou do blog.
Dica: para acompanhar as respostas, acesse com uma conta do Google e marque a opção "Notifique-me".
Atenção: o blogger não permite inclusão de tags nos comentários, por isso, use algum site externo para postar seu código com dúvidas e deixe o link aqui. Exemplo: pastebin.com