Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Caractere ISO-8859-1 trunca texto inserido na coluna utf-8 mysql


Algo em seu código não está lidando com a string como UTF8. Pode ser seu PHP/HTML, pode estar em sua conexão com o banco de dados ou pode ser o próprio banco de dados - tudo deve ser definido como UTF8 consistentemente e, se algo não estiver, a string será truncada exatamente como você ver ao passar por um limite UTF8/não-UTF8.

Vou assumir que seu banco de dados é compatível com UTF8 - isso é mais fácil de verificar. Observe que o agrupamento pode ser definido no nível do servidor, no nível do banco de dados, no nível da tabela e no nível da coluna dentro da tabela. Definir o agrupamento UTF8 na coluna deve substituir qualquer outra coisa para armazenamento, mas os outros ainda serão ativados ao conversar com o banco de dados se também não forem UTF8. Se você não tiver certeza, defina explicitamente a conexão como UTF8 depois de abri-la:
$dbh->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");

Agora seu banco de dados e conexão são UTF8, verifique se sua página da web também é. Novamente, isso pode ser definido em mais de um local (.htaccess, php.ini). Se você não tem certeza / não tem acesso, apenas substitua o que o PHP está pegando como padrão na parte superior da sua página:
<?php ini_set('default_charset', 'UTF-8'); ?>

Observe que você deseja o acima logo no início, antes que qualquer texto seja gerado na sua página. Uma vez que o texto é gerado, é potencialmente tarde demais para tentar especificar uma codificação - você já pode estar bloqueado no que for padrão em seu servidor. Eu também repito isso em meus cabeçalhos (possivelmente um exagero):
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-type" content="text/html; charset=UTF-8">
</head>

E eu o substituo em formulários em que estou pegando dados também:
<FORM NAME="utf8-test" METHOD="POST" ACTION="utf8-test.php" enctype="multipart/form-data" accept-charset="UTF-8">"

Para ser honesto, se você definiu a codificação na parte superior, meu entendimento é que as outras substituições não são necessárias - mas eu as mantenho de qualquer maneira, porque também não quebra nada e prefiro apenas declarar o codificação explicitamente, do que deixar o servidor fazer suposições.

Finalmente, você mencionou que no phpMyAdmin você inseriu a string e ficou como esperado - você tem certeza de que as páginas do phpMyAdmin são UTF8? Eu não acho que eles são. Quando armazeno dados UTF8 do meu código PHP, ele é exibido como caracteres brutos de 8 bits no phpMyAdmin. Se eu pegar a mesma string e armazená-la diretamente no phpMyAdmin, ela parecerá 'correta'. Então, suponho que o phpMyAdmin esteja usando o conjunto de caracteres padrão do meu servidor local, não necessariamente UTF8.

Por exemplo, a seguinte string armazenada da minha página da web:
I can’t wait

Lê assim no meu phpMyAdmin:
I can’t wait

Portanto, tenha cuidado ao testar dessa maneira, pois você realmente não sabe qual codificação o phpMyAdmin está usando para exibição ou conexão com o banco de dados.

Se você ainda estiver tendo problemas, tente meu código abaixo. Primeiro eu crio uma tabela para armazenar o texto em UTF8:
CREATE TABLE IF NOT EXISTS `utf8_test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `my_text` varchar(8000) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

E aqui está um pouco de PHP para testá-lo. Ele basicamente pega sua entrada em um formulário, ecoa essa entrada de volta para você e armazena/recupera o texto do banco de dados. Como eu disse, se você visualizar os dados diretamente no phpMyAdmin, poderá descobrir que não parece certo, mas na página abaixo, ele sempre deve aparecer como esperado, devido à conexão da página e do db estar bloqueada para UTF8.
<?php
  // Override whatever is set in php.ini
  ini_set('default_charset', 'UTF-8');

  // The following should not be required with the above override
  //header('Content-Type:text/html; charset=UTF-8');

  // Open the database
  $dbh = new PDO('mysql:dbname=utf8db;host=127.0.0.1;charset=utf8', 'root', 'password');

  // Set the connection to UTF8
  $dbh->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
  // Tell MySql to do the parameter replacement, not PDO
  $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
  // Throw exceptions (and break the code) if a query is bad
  $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  $id = 0;
  if (isset($_POST["StoreText"]))
  {
    $stmt = $dbh->prepare('INSERT INTO utf8_test (my_text) VALUES (:my_text)');
    $stmt->execute(array(':my_text' => $_POST['my_text']));
    $id = $dbh->lastInsertId();
  }
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional/EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-type" content="text/html; charset=UTF-8">

<title>UTF-8 Test</title>
</head>

<body>

<?php
  // If something was posted, output it
  if (isset($_POST['my_text']))
  {
    echo "POSTED<br>\n";
    echo $_POST['my_text'] . "<br>\n";
  }

  // If something was written to the database, read it back, and output it
  if ($id > 0)
  {
    $stmt = $dbh->prepare('SELECT my_text FROM utf8_test WHERE id = :id');
    $stmt->execute(array(':id' => $id));
    if ($result = $stmt->fetch())
    {
      echo "STORED<br>\n";
      echo $result['my_text'] . "<br>\n";
    }
  }

  // Create a form to take some user input
  echo "<FORM NAME=\"utf8-test\" METHOD=\"POST\" ACTION=\"utf8-test.php\" enctype=\"multipart/form-data\" accept-charset=\"UTF-8\">";

  echo "<br>";

  echo "<textarea name=\"my_text\" rows=\"20\" cols=\"90\">";

  // If something was posted, include it on the form
  if (isset($_POST['my_text']))
  {
    echo $_POST['my_text'];
  }

  echo "</textarea>";

  echo "<br>";
  echo "<INPUT TYPE = \"Submit\" Name = \"StoreText\" VALUE=\"Store It\" />";

  echo "</FORM>";
?>
<br>

</body>

</html>