• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

magnastik

Php e MySQL - Problemas de Charset

18 mensagens neste tópico

Boas!

Estou a fazer uma aplicação em php com ajax e como sabemos o XMLHTTPrequest por defeito trata a informação em UTF-8.

Tenho o mysql em UTF-8, tenho os cabeçalhos nos ficheiros PHP em UTF-8 mas dá-me sempre problemas de caracteres.

Por exemplo, se inserir a informação a apartir de um form num ficheiro PHP a informação fica na base de dados assim: "País" que seria "País", mas quando vou fazer o display no browser está correcto.

Se introduzir directamente num mysql gui manager (no meu caso o SQLyog) então fica bem na base de dados mas ao fazer o display no browser tá baralhado, tipo: "Descri��o do livro" que na BD está "Descrição do livro"

Até já forcei nos ficheiros o php a ter o UTF-8 por defeito com:

<? ini_set(”default_charset”,”UTF-8″); ?>
<meta content=”text/html; charset=UTF-8″ http-equiv=”Content-Type” />

Depois se fizer um output do charset que o php tem por defeito dá:

<?php print_r(iconv_get_encoding()); ?>

E diz-me que está a usar o ISO-8859-1

Já não estou a ver bem isto, se alguém tiver ideias...

Abraços,

magnastik

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Isso também me aconteceu quando usei XMLHTTPRequest num projecto.

Experimenta enviar o header

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

Os do HTML não são muito de fiar ..

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

quando guardas na base de dados podes usar a função htmlentities (http://pt2.php.net/htmlentities) que te converte os caracteres ascii em "entidades" html

eu para alem do meta também envio a informação da pagina de código no header do html

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

li em algum lado que se não enviares o charset no header vais ter probelmas

se não me engano o mysl por defeito usa o iso-8859-1 nas versoes > 5 podes alterar isso e escolher charsets diferentes para campos diferentes da tabela (como dizes que o tens em utf-8 o problema deve ser de não enviares o chaset no header)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Estive a falar com o magnastik hoje de manhã no msn fizemos alguns testes e acho que encontramos a solução.

A solução é bastante simples, mas vou colocar aqui os 2 ficheiros como exemplo para o caso de alguém que esteja interessado ver como é simples de usar Ajax, usando a livraria prototype (http://www.prototypejs.org).

O ficheiro que irá fazer a chamada (é necessário ter pelo menos o ficheiro prototype.js na mesma pasta, ou noutra pasta, mudando o caminho da tag)

<script src="prototype.js" type="text/javascript"></script>

teste_charset.php

<html>
<head>
<title>Prototype :: Ajax Teste Charset</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<script src="prototype.js" type="text/javascript"></script>
<style>
	body {
		font-family: lucida grande, verdana, sans-serif;
		font-size: 12px;
	}

	table { border-collapse: collapse; border: 1px solid #ddd; }
	th { background: #eee; color: #333; }
	td { color: #333; padding: 3px; }
</style>
</head>


<body>

<p><a href="#" onclick="javascript:chamada();">Resultados</a></p>

<div id="conteudo">(Clique no link acima para carregar o conteudo..)</div>

<script type="text/javascript">
function chamada(){
new Ajax.Updater('conteudo', 'resultados.php', {
	method: 'get',
	encoding: 'iso-8859-1'
});
}
</script>

</body>
</html>

Penso que a linha mais importante é a de javascript que define o encoding: 'iso-8859-1', sem essa linha, o pedido que fazemos será interpretado como UTF-8, logo os acentos não serão mostrados correctamente.

O ficheiro com os resultados...

resultados.php

<?php
/**
* <!> esta linha é importante
* envia o charset como iso-8859-1
* senão o xmlhttprequest irá interpretar 
* como utf-8 pois é a codificação default
* dos ficheiros XML
*/
header('Content-Type: text/html; charset=iso-8859-1');


/**
* OK, conexão à base de dados
* substituir pelos vossos dados de acesso 
*
* De notar, a base de dados que usei como teste
* está em Latin1 (ISO-8859-1)
*/
mysql_pconnect('localhost', 'utilizador', 'senha');
mysql_select_db('base_de_dados');

$q = mysql_query('SELECT * FROM tabela LIMIT 10');
?>


<table width="100%" cellspacing="1">
<tr>
<th>CampoX</th>
<th>CampoY</th>
</tr>

<?php while($l = mysql_fetch_assoc($q)): ?>
<tr>
<td><?=$l['campoX'];?></td>
<td><?=$l['campoY'];?></td>
</tr>
<?php endwhile; ?>

</table>

Neste ficheiro é necessário usar a tag

header('Content-Type: text/html; charset=iso-8859-1');

pois apesar de no teste_charset.php dizermos que o pedido virá em ISO-8859-1, ele acaba por ser interpretado como UTF-8 sem esta linha.

Este teste funcionou com uma base de dados MySQL em Latin1, onde já tinha dados inseridos.

Penso que assim já não deve haver mais problemas com a codificação de caracteres, a solução do Sven também funciona, mas seria sempre necessário fazer o encode ao inserir na BD e o decode ao devolver da BD.

Espero que possa ser útil para mais alguém e qualquer dúvida estão à vontade de colocar :)

Abraço,

milks

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Viva pessoal!

Por exemplo, se inserir a informação a apartir de um form num ficheiro PHP a informação fica na base de dados assim: "País" que seria "País", mas quando vou fazer o display no browser está correcto.

Estou exactamente com o mesmo problema!

Apesar de criar as tabelas no MySQL com o charset=utf8,

CREATE TABLE tabela (campos) ENGINE = INNODB DEFAULT CHARSET=utf8

definir o charset utf8 no documento html com

<meta http-equiv="content-type" content="text/html; charset=UTF-8">

e alterar o charset para utf8 nos cabeçalhos http através do php com

header('content-type: text/html; charset=UTF-8');

aparece tudo bem, mas na base de dados os caracteres acentuados ficam uma miséria.

Não cheguei a experimentar o htmlentities(), mas também não acho que seja uma boa solução.

Mais alguma ideia?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

então a solução é acertares o chaset da bd com o charset do site

mas porque é que o htmlentities() não é uma boa solução ?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

então a solução é acertares o chaset da bd com o charset do site

Não sei se me expliquei bem, mas tudo o que envolve charsets foi alterado para UTF-8.

mas porque é que o htmlentities() não é uma boa solução ?

Porque não faz sentido (pelo menos para mim), pôr htmlentities() em tudo o que $_POST['variavel'].
0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

então a solução é acertares o chaset da bd com o charset do site

Não sei se me expliquei bem, mas tudo o que envolve charsets foi alterado para UTF-8

[/Quote]

Como é óbvio não está se não não tinhas esse problema

qual é a versão do mysql que usas ? e q a ferramenta que usas para ver os registos da db suporta utf-8

não queres postar aqui o sql de criação da tabela?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O htmlentities() é uma solução, se usares o parametro ENQ_QUOTES, ficas com as ' e " em entidades HTML, logo é um passo em direcção à segurança.

Mas apesar de funcionar, preferia não ter de usar, preferia que os dados na BD ficassem sem ser codificados em entidades HTML (de forma a poder aceder usando o MySQL Query Browser por exemplo).

Sei que utf8_decode() quando estão a imprimir os valores na página também funcionam, mas sou preguiçoso, e não quero ter de tar a adicionar um utf8_decode() a todos os meus echos/prints etc...

Apesar da solução que dei em cima funcionar, foi só testada em casos que se pretendia devolver dados da BD, ao inserir, também tive problemas, fiz alguns testes, mas ainda vou perder algum tempo nisso durante o fim de semana, pois não cheguei a nenhum resultado que me agradasse, na BD acaba sempre por ficar ilegivel (testei com o Navicat MySQL 7.1.5 e MySQL Q.B. e ambos têm suporte para Unicode)

O magnastik disse que ia dar com força neste tema o fim de semana.. espero alguma novidade.

Entretanto vou ver se leio algo sobre encodings e charsets.. acho que estou a precisar

E como disse, vou testar algo a ver se encontro também uma solução..

Cumps,

milks

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Só agora vi que versão do MySQL estou a usar. É a 4.0.24 (acho que deve ser por isso que estou a ter problemas  :angry1:).

Eis uma das tabelas que estou a criar:

CREATE TABLE contact_country (
contact_country_id SERIAL,
contact_country_name VARCHAR(32) NOT NULL UNIQUE,
PRIMARY KEY (contact_country_id)
) ENGINE = INNODB DEFAULT CHARSET=utf8;

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Bem haja!

Já agora, estive a ver uma página sobre PHP e encodings, e além do já discutido

<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> e do header('Content-Type: text/html; charset=utf-8');, também sugerem adicionar accept-charset="utf-8" no início do form.

Exemplo:

<form accept-charset="utf-8" method="post">

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Se tiveres a BD em Latin1, podes usar iconv("UTF-8", "ISO-8859-1", $_POST['index']); que penso funcionará bem. Mas é a questão de teres de usar uma função para a codificação (apenas tens de fazer ao inserir) e tens de passar os teus scripts para ISO e não UTF. Eu até não me importo de passar os meus valores por uma função, mas que fosse do lado do javascript e que apenas tivesse de usar 1 vez.. acho que encodeURIComponent() resolve, mas ainda não testei, foi apenas pelo que li na net..

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Pois...

como te disse também estive a ler sobre isso e a testar, mas temos pena, o iconv só bem embebido a partir do PHP 5, por isso quem tiver versões anteriores tem duas saídas:

1º Tem acesso à configuração do php.ini e pode fazer o enable da função

2º Não tem acesso como por exemplo nos sites alojados online e ardeu!

Por isso, o iconv não é assim uma solução tão linear.

Abraços,

MagNastiK

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Exemplo:

<form accept-charset="utf-8" method="post">

Se bem que acho que isto não faz muito sentido e vou explicar porquê.

Porque geralmente quem desenvolve php e junta "algum" ajax nem precisa sequer de definir a tag FORM. Aliás normalmente não definem mesmo as tags FORM, já que por exemplo no prototype JS podes usar a função $F para ires buscar o valor de um campo de um form, mesmo que não haja Tag form definida.

Acho que o problema é mesmo não poder utilizar-se o encoding todo em ISO-8859-1, já que aí resolveria todos os problemas.

Nomeadamente, quando temos já um monte de registos a inserir na BD e podemos usar um GUI para os inserir de uma só vez. Mas no caso da utilização do html entities para codificar os caracteres então vamos ter o problema de depois não ser um edição simples.

Estive a pensar e também existe outra alternativa, meio rudimentar, mas resolve esse problema.

Imaginemos que vamos inserir na BD a informação codificada com o html_entities, se tivermos mais info a colocar que não esteja codificada com o html_entities, podemos sempre coloca-la em primeiro lugra, cirar um script que faz o retrieve e um update da info já com o html_entities e depois pronto.. já fica codificada.

De qualquer forma tenho estado no canal de IRC do Prototype JS e se houver alguma alternativa para contornar este berbicacho eu coloco aqui.

Abraços,

MagNastiK

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

então a solução é acertares o chaset da bd com o charset do site

Não sei se me expliquei bem, mas tudo o que envolve charsets foi alterado para UTF-8.

mas porque é que o htmlentities() não é uma boa solução ?

Porque não faz sentido (pelo menos para mim), pôr htmlentities() em tudo o que $_POST['variavel'].

Bem é uma questão de opinião, mas da mesma forma que é boa prática fazeres o escape para prevenir possíveis SQL Injections podias criar uma função que fizesse tudo de uma vez... nem precisava de ter um nome grande podia ser a() ;)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

então a solução é acertares o chaset da bd com o charset do site

Não sei se me expliquei bem, mas tudo o que envolve charsets foi alterado para UTF-8.

mas porque é que o htmlentities() não é uma boa solução ?

Porque não faz sentido (pelo menos para mim), pôr htmlentities() em tudo o que $_POST['variavel'].

Bem é uma questão de opinião, mas da mesma forma que é boa prática fazeres o escape para prevenir possíveis SQL Injections podias criar uma função que fizesse tudo de uma vez... nem precisava de ter um nome grande podia ser a() ;)

function a($s){ return mysql_real_string_escape(htmlentities($s)); } 

Uso:

$string = "lol";
$string = a($string);
echo $string;

ou queres recursivamente e com referências?

function a(&$x){
if(gettype($x) == "string"){ $x = mysql_real_string_escape(htmlentities($x)); return $x; }
if(gettype($x) == "array"){ foreach($x as $k => $v){ $x[$k] = a($v); } return $x; }
return false;
}

Ora bem, é preciso explicar este código? ;)

Uso:

$string = "blah";
a($string);
echo $string;

ou

$array = array("lol", array("lolada", "lolix", array("ahahah", "lulz", "uz", "p@p allez", "lol"), "lolz");
a($array);
var_dump($array);

Atenção, não testei isto, mas penso que funciona. ;)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Eu resolvi este problema criando uma função para fazer o tratamento de dados assim

function tratardados($string) {
$string = mysql_real_escape_string($string);
$string = htmlentities($string, ENT_QUOTES, "UTF-8");
$string = stripslashes($string);
return $string;
}

$id_categoria_noticia	= tratardados($_POST['id_categoria_noticia']);
$titulo                             = tratardados($_POST['titulo']);
$descricao                     = tratardados($_POST['descricao']);
//$destaque                   = tratardados($_POST['destaque']);
$status                          = tratardados($_POST['status']);
$msg                             = tratardados($_POST['msg']);

Editado por Hijack
0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora