All posts tagged mysql

Analisando problema de encoding PHP + Mysql – LATIN1 e UTF8

Salve!

Hoje entrei em colapso novamente com o famoso problema de encoding do PHP com Mysql.

quem não teve esse problema uma vez na vida atire a primeira pedra!

Resolvi então fazer uma analise completa de possíveis resultados.

Vamos iniciar o teste com 2 bases de dados, uma com encoding em latin1 (default) e outra com utf8_general_ci:

Comandos para criação db test_latin:

CREATE DATABASE test_latin;
USE test_latin;

CREATE TABLE `table_latin` (
  `id` int(11) NOT NULL,
  `texto` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `table_utf` (
  `id` int(11) NOT NULL,
  `texto` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Comandos para criação db test_utf:

CREATE DATABASE test_utf;
USE test_utf;

CREATE TABLE `table_latin` (
  `id` int(11) NOT NULL,
  `texto` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `table_utf` (
  `id` int(11) NOT NULL,
  `texto` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Sendo assim temos todas as possibilidades de tentativas para o teste, agora o próximo passo é crias alguns registros e ver como eles se comportam.

Para isso precisamos criar dois arquivos parecidos em seu conteúdo e com codificações diferentes, um em utf8 (sem BOM) e outro em ISO-8859-1 (ANSI), com o seguinte conteúdo:

Não se preocupe em copiar o código, o download está no final do post.

Arquivo UTF8:

<?php
$db_latin	= new mysqli('localhost','root','','test_latin');
$db_utf		= new mysqli('localhost','root','','test_utf');

if(!$db_latin){
	exit('Erro Conexão Latin: '.$db_latin->error);
}

if(!$db_utf){
	exit('Erro Conexão UTF: '.$db_utf->error);
}

/**
 * TESTES
 * id - Item
 * // DB LATIN1
 * 1 - Insert padrão TABLE LATIN
 * 2 - Insert padrão TABLE UTF
 * 3 - Insert TABLE LATIN	- UTF8_DECODE
 * 4 - Insert TABLE LATIN	- UTF8_ENCODE
 * 5 - Insert TABLE UTF		- UTF8_DECODE
 * 6 - Insert TABLE UTF		- UTF8_ENCODE
 * // DB UTF8_GENERAL_CI
 * 7  - Insert padrão TABLE LATIN
 * 8  - Insert padrão TABLE UTF
 * 9  - Insert TABLE LATIN		- UTF8_DECODE
 * 10 - Insert TABLE LATIN		- UTF8_ENCODE
 * 11 - Insert TABLE UTF		- UTF8_DECODE
 * 12 - Insert TABLE UTF		- UTF8_ENCODE
 */

/**
 * CONTEUDO
 */
$key = "Órfão";
$key_encode = utf8_encode($key);
$key_decode = utf8_decode($key);

/**
 * INSERT LATIN
 */
$query = $db_latin->query("INSERT INTO table_latin (id, texto) VALUES (1, '{$key}');");			// 1  - Insert padrão TABLE LATIN

if(!$query){
	exit('Erro Query: '. $db_latin->error . __LINE__);
}

$query = $db_latin->query("INSERT INTO table_utf (id, texto) VALUES (2, '{$key}');");				// 2  - Insert padrão TABLE UTF

if(!$query){
	exit('Erro Query: '. $db_latin->error . __LINE__);
}

$query = $db_latin->query("INSERT INTO table_latin (id, texto) VALUES (3, '{$key_decode}');");	// 3  - Insert TABLE LATIN		- UTF8_DECODE

if(!$query){
	exit('Erro Query: '. $db_latin->error . __LINE__);
}

$query = $db_latin->query("INSERT INTO table_latin (id, texto) VALUES (4, '{$key_encode}');");	// 4  - Insert TABLE LATIN		- UTF8_ENCODE

if(!$query){
	exit('Erro Query: '. $db_latin->error . __LINE__);
}

$query = $db_latin->query("INSERT INTO table_utf (id, texto) VALUES (5, '{$key_decode}');");		// 5  - Insert TABLE UTF		- UTF8_DECODE

if(!$query){
	exit('Erro Query: '. $db_latin->error . __LINE__);
}

$query = $db_latin->query("INSERT INTO table_utf (id, texto) VALUES (6, '{$key_encode}');");		// 6  - Insert TABLE UTF		- UTF8_ENCODE

if(!$query){
	exit('Erro Query: '. $db_latin->error . __LINE__);
}

/**
 * INSERT UTF
 */
$query = $db_utf->query("INSERT INTO table_latin (id, texto) VALUES (7, '{$key}');");				// 7  - Insert padrão TABLE LATIN

if(!$query){
	exit('Erro Query: '. $db_utf->error . __LINE__);
}

$query = $db_utf->query("INSERT INTO table_utf (id, texto) VALUES (8, '{$key}');");				// 8  - Insert padrão TABLE UTF 

if(!$query){
	exit('Erro Query: '. $db_utf->error . __LINE__);
}

$query = $db_utf->query("INSERT INTO table_latin (id, texto) VALUES (9, '{$key_decode}');");		// 9  - Insert TABLE LATIN		- UTF8_DECODE

if(!$query){
	exit('Erro Query: '. $db_utf->error . __LINE__);
}

$query = $db_utf->query("INSERT INTO table_latin (id, texto) VALUES (10, '{$key_encode}');");		// 10 - Insert TABLE LATIN		- UTF8_ENCODE

if(!$query){
	exit('Erro Query: '. $db_utf->error . __LINE__);
}

$query = $db_utf->query("INSERT INTO table_utf (id, texto) VALUES (11, '{$key_decode}');");		// 11 - Insert TABLE UTF		- UTF8_DECODE

if(!$query){
	exit('Erro Query: '. $db_utf->error . __LINE__);
}

$query = $db_utf->query("INSERT INTO table_utf (id, texto) VALUES (12, '{$key_encode}');");		// 12 - Insert TABLE UTF		- UTF8_ENCODE

if(!$query){
	exit('Erro Query: '. $db_utf->error . __LINE__);
}
?>

Arquivo ISO-8859-1:

<?php
$db_latin	= new mysqli('localhost','root','','test_latin');
$db_utf		= new mysqli('localhost','root','','test_utf');

if(!$db_latin){
	exit('Erro Conexão Latin: '.$db_latin->error);
}

if(!$db_utf){
	exit('Erro Conexão UTF: '.$db_utf->error);
}

/**
 * TESTES
 * id - Item
 * // DB LATIN1
 * 13 - Insert padrão TABLE LATIN
 * 14 - Insert padrão TABLE UTF
 * 15 - Insert TABLE LATIN		- UTF8_DECODE
 * 16 - Insert TABLE LATIN		- UTF8_ENCODE
 * 17 - Insert TABLE UTF		- UTF8_DECODE
 * 18 - Insert TABLE UTF		- UTF8_ENCODE
 * // DB UTF8_GENERAL_CI
 * 19  - Insert padrão TABLE LATIN
 * 20  - Insert padrão TABLE UTF
 * 21  - Insert TABLE LATIN		- UTF8_DECODE
 * 22 - Insert TABLE LATIN		- UTF8_ENCODE
 * 23 - Insert TABLE UTF		- UTF8_DECODE
 * 24 - Insert TABLE UTF		- UTF8_ENCODE
 */

/**
 * CONTEUDO
 */
$key = "Órfão";
$key_encode = utf8_encode($key);
$key_decode = utf8_decode($key);

/**
 * INSERT LATIN
 */
$query = $db_latin->query("INSERT INTO table_latin (id, texto) VALUES (13, '{$key}');");			// 13  - Insert padrão TABLE LATIN

if(!$query){
	exit('Erro Query: '. $db_latin->error . __LINE__);
}

$query = $db_latin->query("INSERT INTO table_utf (id, texto) VALUES (14, '{$key}');");				// 14  - Insert padrão TABLE UTF

if(!$query){
	exit('Erro Query: '. $db_latin->error . __LINE__);
}

$query = $db_latin->query("INSERT INTO table_latin (id, texto) VALUES (15, '{$key_decode}');");	// 15  - Insert TABLE LATIN		- UTF8_DECODE

if(!$query){
	exit('Erro Query: '. $db_latin->error . __LINE__);
}

$query = $db_latin->query("INSERT INTO table_latin (id, texto) VALUES (16, '{$key_encode}');");	// 16  - Insert TABLE LATIN		- UTF8_ENCODE

if(!$query){
	exit('Erro Query: '. $db_latin->error . __LINE__);
}

$query = $db_latin->query("INSERT INTO table_utf (id, texto) VALUES (17, '{$key_decode}');");		// 17  - Insert TABLE UTF		- UTF8_DECODE

if(!$query){
	exit('Erro Query: '. $db_latin->error . __LINE__);
}

$query = $db_latin->query("INSERT INTO table_utf (id, texto) VALUES (18, '{$key_encode}');");		// 18  - Insert TABLE UTF		- UTF8_ENCODE

if(!$query){
	exit('Erro Query: '. $db_latin->error . __LINE__);
}

/**
 * INSERT UTF
 */
$query = $db_utf->query("INSERT INTO table_latin (id, texto) VALUES (19, '{$key}');");				// 19  - Insert padrão TABLE LATIN

if(!$query){
	exit('Erro Query: '. $db_utf->error . __LINE__);
}

$query = $db_utf->query("INSERT INTO table_utf (id, texto) VALUES (20, '{$key}');");				// 20  - Insert padrão TABLE UTF 

if(!$query){ exit('Erro Query: '. $db_utf->error . __LINE__); }

$query = $db_utf->query("INSERT INTO table_latin (id, texto) VALUES (21, '{$key_decode}');");		// 21  - Insert TABLE LATIN		- UTF8_DECODE

if(!$query){
	exit('Erro Query: '. $db_utf->error . __LINE__);
}

$query = $db_utf->query("INSERT INTO table_latin (id, texto) VALUES (22, '{$key_encode}');");		// 22 - Insert TABLE LATIN		- UTF8_ENCODE

if(!$query){
	exit('Erro Query: '. $db_utf->error . __LINE__);
}

$query = $db_utf->query("INSERT INTO table_utf (id, texto) VALUES (23, '{$key_decode}');");		// 23 - Insert TABLE UTF		- UTF8_DECODE

if(!$query){
	exit('Erro Query: '. $db_utf->error . __LINE__);
}

$query = $db_utf->query("INSERT INTO table_utf (id, texto) VALUES (24, '{$key_encode}');");		// 24 - Insert TABLE UTF		- UTF8_ENCODE

if(!$query){
	exit('Erro Query: '. $db_utf->error . __LINE__);
}
?>

Lembre-se de salvar o arquivo com o encoding diferente para que os testes tenham mais precisão, no teste eu salvei como insert.php (UTF8) e insert_iso.php(ANSI).

Executando os 2 os resultados das tabelas foi esse:

`test_utf`.`table_utf`
id texto
8 Órfão
11 Órfão
12 Órfão
20 Órfão
23 ?rf?o
24 Órfão
`test_utf`.`table_latin`
id texto
7 Órfão
9 Órfão
10 Órfão
19 Órfão
21 ?rf?o
22 Órfão
`test_latin`.`table_latin`
id texto
1 Órfão
3 Órfão
4 Órfão
13 Órfão
15 ?rf?o
16 Órfão
`test_latin`.`table_utf`
id texto
2 Órfão
5 Órfão
6 Órfão
14 Órfão
17 ?rf?o
18 Órfão

O mais incrível é isso, em TODAS as tabelas os resultados são os mesmos, esses testes foram feitos no Windows 7 com XAMPP, se alguem obter resultados diferentes em outros OS ou no Windows mesmo, me informe que eu atualizo o post.

Eu prefiro utilizar nos meus projetos sempre arquivos como UTF-8 assim como o DB, então a solução é aderir ao utf8_decode em inserts.

Switch to our mobile site