MySQL задыхается от кудрявых (умных) котировок

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

Регулярные кавычки экранируются, но некоторые другие цитаты отсутствуют. Например, строка:

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

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

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

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

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

Поэтому PHP считает, что курчавая цитата прекрасна, но MySQL теряет строку. Однако MySQL не дает никаких ошибок.

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

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

«В Moe's – единственный символ в вашей строке примера, который недействителен, если эта строка кодируется латином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 указывает, что «мой» набор символов подключения – 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?