CataBits ~ Acentuação em PHP com MySQL Acentuação em PHP com MySQL – CataBits
Acentuação em PHP com MySQL
Por Luferat em 3 de novembro de 2019.
Você está dando os primeiros passos na linguagem PHP se relacionando com o banco de dados MySQL ou MariaDB e começa a se deparar com problemas de acentuação no navegador, ou seja, no lugar dos acentos e do "ç" aparecem caracteres estranhos ou losangos com um "?" dentro. O mesmo acontece quando você salva alguma coisa no banco de dados. Isso provavelmente acontece porque os diversos sistemas estão conversando, usando tabelas de caracteres diferentes.
Com a chegada e popularização do HTML5, isso fica mais evidente, já que, por padrão, páginas HTML5 usam o conjunto de caracteres UTF-8.
Assim, é importante verificar se todos os sistemas também usam UTF-8 que é uma charset universal que pode representar e converter caracteres de praticamente qualquer sistema, porque usa como base o padrão Unicode.
Criando sites em UTF-8
Se você usa PHP, a primeira linha a ser interpretada pelo seu script deve ser:
No HTML5, como já vimos, é importante que a linha abaixo esteja dentro da tag <header>...</header>:
Outra coisa importante é setar o UTF-8 como conjunto de caracteres padrão do SGBD, quando este se relacionar com seus scripts PHP. Para isso, costumo criar um arquivo de configuração inicial das páginas, que é "incluído" em todos os scripts do site, antes de qualquer outro código PHP ou de "fron-end". Observe que isso já faz a conexão com o banco de dados e seta as queries para UTF-8:
# Informa qual o conjunto de caracteres será usado
$conn = new mysqli('servidor', 'usuario', 'senha', 'banco');
# Trap de erros de conexão
if ($conn->connect_error) die("Erro no servidor: " . $conn->connect_error);
# Aqui está o segredo da conexão em UTF-8
$conn->query('SET character_set_connection=utf8');
$conn->query('SET character_set_client=utf8');
$conn->query('SET character_set_results=utf8');
# Meses e dias da semana em pt/BR
$conn->query('SET lc_time_names = "pt_BR"');
# Outras configurações iniciais
O código acima faz a conexão com o MySQL usando a biblioteca "MySQLi" e seta todas as trocas de dados entre banco de dados e o PHP para UTF-8. Ainda aproveitei para setar o MySQL para traduzir os nomes dos meses e dias da semana para português/Brasil.
Bases de dados em UTF-8
No MySQL ou MariaDB, sempre crie bancos de dados com o conjunto de caracteres UTF-8, como no exemplo abaixo:
CREATE DATABASE bancoteste CHARACTER SET utf8 COLLATE utf8_general_ci;
No exemplo, definimos o conjunto de caracteres a ser usando com o banco de dados como UTF-8 e também o agrupamento usado nas consultas. No caso do agrupamento, existem várias alternativas onde, algumas são:
Consultas em qualquer idioma devem usar o conjunto UTF-8 e são "case-insensitive", ou seja, ignoram a diferença entre maiúsculas e minúsculas. Assim, a query:
SELECT * FROM usuario WHERE nome = 'Joca Silva';
tem o mesmo resultado.
A "consulta sueca" também deve usar o conjunto UTF-8, são "case-insensitive", ou seja, ignoram a diferença entre maiúsculas e minúsculas. A diferença para utf8_general_ci é que esta ignora os acentos. Assim, todas as query abaixo retornam o mesmo resultado:
SELECT * FROM cadastro WHERE cidade = "São Paulo";
SELECT * FROM cadastro WHERE cidade = "Sao Paulo";
Essa é a teoria (que está na documentação do MySQL) porque na prática, talvez por questões relacionadas ao sistema operacional e ao modo de compilação do SGBD, as consultas a tabelas com collate utf8_swedish_ci se comportam de forma diferente.
utf8_bin,/dt>
A "consulta binária" é bem mais rígida já que, em vez de usar a tabela de caracteres, faz uma consulta binária. Isso significa que maiúsculas são diferentes de minúsculas. As queries abaixo retornam resultados diferentes:
SELECT * FROM sistema WHERE empresa = "Microsoft";
Você pode usar collates e conjuntos de caracteres diferentes para tabelas diferentes de um banco de dados. Basta criar a tabela conforme o exemplo:
data TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
corpo LONGTEXT,
status ENUM('ativo', 'inativo', 'revisando', 'apagado') DEFAULT 'ativo'
Assim, mesmo estando em um banco de dados, por exemplo, utf8_general_ci, as consultas nesta tabela serão "case-sensitive", ou seja, utf8_bin.
Vimos então que, para resolver problemas de acentuação entre o PHP e o MySQL, bastam algumas linhas de código adicionais e um cuidado especial ao criar bancos de dados e tabelas.
Se gostou do conteúdo, tem alguma dica, sugestão de melhoria ou achou algum "bug", não deixe de me contactar.