CataBits

CataBits

Acentuação em PHP com MySQL

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.

HTML, CSS, JavaScript, PHP e MySQL

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.

<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<title>Minha página</title>
</head>
<body>
...
</body>
</html>

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:

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

No HTML5, como já vimos, é importante que a linha abaixo esteja dentro da tag <header>...</header>:

<meta charset="UTF-8">

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:

<?php
# Informa qual o conjunto de caracteres será usado
header('Content-Type: text/html; charset=utf-8');

# Conecta ao banco de dados
$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 NAMES 'utf8'");
$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:

utf8_general_ci
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';

e a query:

SELECT * FROM usuario WHERE nome = 'joca silva';

tem o mesmo resultado.

utf8_swedish_ci
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";
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";
SELECT * FROM sistema WHERE empresa = "microsoft";
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:

CREATE TABLE documentos (
    id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
    data TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    titulo VARCHAR(200) NOT NULL,
    corpo LONGTEXT,
    status ENUM('ativo', 'inativo', 'revisando', 'apagado') DEFAULT 'ativo'
) CHARACTER SET utf8 COLLATE utf8_bin;

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.

Conclusão

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.

E, até a próxima!

Ao clicar em "Aceitar cookies", você concorda que o CataBits pode guardar cookies no seu dispositivo e utilizar essas informações de acordo com as nossas Políticas de Cookies.
Aceitar cookies!
Não aceito!