MySQL задыхается от кудрявых (умных) цитат - PullRequest
8 голосов
/ 23 августа 2009

Я вставляю некоторые данные в базу данных из формы. Я использую addslashes для экранирования текста (также пытался mysql_real_escape_string с тем же результатом).

Обычные кавычки экранированы, но некоторые другие кавычки - нет. Например, строка:

Кровь Гомера становится секретным ингредиентом в новом пиве Мо.

преобразуется в:

Кровь Гомера становится секретным ингредиентом в новом пиве Мо.

Я не думал, что фигурные кавычки будут иметь значение без отступления, но в базу данных вставляется только этот текст:

Кровь Гомера становится секретным ингредиентом в Мо

Таким образом, PHP считает, что вьющиеся кавычки в порядке, но MySQL теряет строку. MySQL не дает никаких ошибок, хотя.

Ответы [ 2 ]

7 голосов
/ 23 августа 2009

'' в Мо '- это единственный символ в вашем примере строки, который не будет действительным, если эта строка закодирована в латинице 1, но ваш сервер mysql ожидает utf8.

Простая демонстрация:

<?php
function foo($s) {
    echo 'len=', strlen($s), ' ';
  for($i=0; $i<strlen($s); $i++) {
    printf('%02X ', ord($s[$i]));
  }
  echo "\n";
}

 // my file is latin1 encoded and so is the string literal
foo('Moe’s');
// now try it with an utf8 encoded string
foo( utf8_encode('Moe’s') );

отпечатков

len = 5 4D 6F 65 92 73
len = 6 4D 6F 65 C2 92 73

Поэтому возникает вопрос: вы кормите сервер mysql чем-то в «неправильной» кодировке?
Каждое соединение имеет кодировку соединения, и сервер MySQL ожидает, что ваш клиент (скрипт php) отправит данные, закодированные в этом наборе символов. Вы можете узнать, что такое кодировка соединения с

SHOW VARIABLES LIKE '%character%'

как в

$mysql = mysql_connect('..', '..', '..') or die(mysql_error());
mysql_select_db('..', $mysql) or die(mysql_error());

$query = "SHOW VARIABLES like '%character%'";
$result = mysql_query($query, $mysql) or die(__LINE__.mysql_error());
while( false!==($row=mysql_fetch_array($result, MYSQL_ASSOC)) ) {
  echo join(', ', $row), "\n";
}

Это должно напечатать что-то вроде

character_set_client, utf8
character_set_connection, utf8
character_set_database, latin1
character_set_filesystem, binary
character_set_results, utf8
character_set_server, utf8
character_set_system, utf8

и character_set_connection, utf8 означают, что набор символов "my" для подключения - utf8, то есть сервер mysql ожидает от клиента кодированных символов utf8 (php). Что такое "ваша" кодировка соединения?

Затем взгляните на фактическую кодировку строки параметров, т. Е. Если у вас было

$foo = mysql_real_escape_string($_POST['foo'], $mysql);

заменить это на

echo '<div>Debug hex($_POST[foo])=';
for($i=0; $i<strlen($s); $i++) {
    printf('%02X ', ord($_POST['foo'][$i]));
}
echo "</div>\n";
$foo = mysql_real_escape_string($_POST['foo'], $mysql);

и проверьте, какова действительная кодировка вашей входной строки. Это печатает 92 или C2 92?

7 голосов
/ 23 августа 2009

Я бы искал несоответствие между кодировкой символов, используемой в вашем веб-интерфейсе, и кодировкой, используемой на уровне базы данных. Если ваш веб-интерфейс использует, например, UTF-8, а ваша база данных использует кодировку MySQL по умолчанию latin1, то вам нужно настроить таблицы с DEFAULT CHARSET=utf8.

Используйте mysql_real_escape_string() или mysqli, кстати. addslashes() is NOT адекватная защита от SQL-инъекций.

...