Хранение сериализованного объекта в базе данных MySql

У меня есть большой объект php, который я хочу сериализовать и сохранить в базе данных MySql. Кодировка таблицы UTF-8 и столбец для хранения кодирования сериализованного объекта также UTF-8,

Проблема в том, что объект содержит текстовую строку, содержащую французские символы.

Например:

Merci d'avoir passé commande avec Lovre. Voici le récapitulatif de votre commande 

Когда я сериализую объект, то снова десериализую его непосредственно, строка будет сохранена и будет в правильном формате.

Однако, когда я сохраняю сериализованный объект в базе данных MySql, затем извлекаю его снова, затем десериализую, строка становится такой:

Merci d'avoir passé commande avec Lovre. Voici le récapitulatif de votre commande 

Что-то идет не так, когда я сохраняю объект в базе данных.

Заметки:

  • Объект хранится с помощью propel ORM.
  • Тип столбца text,
  • Строка сохраняется и читается из HTML-файла.

4 ответа

Решение

Строки, созданные serialize являются двоичными строками, они не имеют определенной кодировки charset, а представляют собой просто "массив" байтов (где один байт равен 8 битам, октет).

Если вы сейчас возьмете такую ​​строку и скажете своей базе данных, что она закодирована в LATIN-1, и ваша база данных сохранит ее в текстовом поле с кодировкой UTF-8, база данных будет прозрачно менять кодировку с LATIN-1 на UTF-8. UTF-8 - это кодировка кодировки, которая использует более одного байта на символ для некоторых символов, например тех, которые вы задаете в своем вопросе, например é,

Характер é затем сохраняется как é внутри базы данных, которая является байтовой последовательностью UTF-8 для é,

Если вы сейчас получите данные из базы данных, не указав, в какой кодировке они вам нужны, база данных вернет их как UTF-8.

Сейчас unserialize возникла проблема, потому что двоичная строка была модифицирована таким образом, что делает ее недействительной.

Вместо этого вам нужно либо указать вашей базе данных, что она не должна изменять кодировку, когда хранит сериализованную строку, например, выбрав правильный тип столбца и кодировку (двоичное поле, BLOB - документы двоичных больших объектовMySQL, см. Также двоичные типыPropel Docs) -или- когда вы извлекаете данные из базы данных, вы возвращаете кодировку кодировки обратно в исходный формат. Первый подход (двоичное поле) лучше, потому что это именно то, что вы ищете.

Для данных, которые уже были сохранены в базе данных в неправильном формате, вам необходимо исправить данные. Для этого сначала необходимо выяснить, какое перекодирование было применено, например, из какой кодировки в какую. Я предполагаю, что это ЛАТИН-1, но нет никакой гарантии. Вам нужно проверить кодировку данных вашего текущего приложения и процессов, чтобы выяснить это.

После того, как вы узнали, закодируйте значения обратно из UTF-8 в исходную кодировку.

Убедитесь, что везде используете utf-8 - похоже, вы что-то пропустили.

в вашем случае, я думаю, что вы забыли установить правильный набор символов для подключения к базе данных (используя SET NAMES заявление или mysql_set_charset ()) - но это трудно сказать, не видя ваш код (и я не знаю, propel).

ниже приводится цитата из chazomaticus, который на протяжении всего пути дал идеальный ответ в UTF-8, перечисляя все вопросы, о которых вы должны позаботиться:

Место хранения:

  • Уточнить utf8_unicode_ci (или эквивалентный) сопоставление для всех таблиц и текстовых столбцов в вашей базе данных. Это заставляет MySQL физически хранить и извлекать значения в UTF-8.

индексирование:

  • В PHP, в какой бы оболочке БД вы не использовали, вам нужно установить кодировку соединения в utf8. Таким образом, MySQL не выполняет преобразование из своего собственного UTF-8, когда передает данные в PHP. * Обратите внимание, что если вы не используете оболочку БД, вам, вероятно, придется выполнить запрос, чтобы сообщить MySQL, что вы получите результаты в UTF-8: SET NAMES 'utf8' (как только вы подключитесь).

Доставка:

  • Вы должны указать PHP, чтобы он доставлял правильные заголовки клиенту, поэтому текст будет интерпретироваться как UTF-8. В PHP вы можете использовать default_charset php.ini или вручную введите Content-Type Заголовок себя, который просто больше работы, но имеет тот же эффект.

Подача конкурсных предложений:

  • Вы хотите, чтобы все данные, отправленные вам браузерами, были в формате UTF-8. К сожалению, единственный способ надежно сделать это - добавить accept-charset приписать всем своим <form> теги: <form ... accept-charset="UTF-8">,
  • Обратите внимание, что спецификация W3C HTML гласит, что клиенты "должны" по умолчанию отправлять формы обратно на сервер в любой кодировке, которую обслуживал сервер, но это, по-видимому, только рекомендация, поэтому необходимо указывать явное в каждом <form> тег.
  • Хотя на этом фронте вы все равно захотите проверить каждую отправленную строку как действительную UTF-8, прежде чем пытаться сохранить ее или использовать где-либо еще. РНР mb_check_encoding() делает трюк, но вы должны использовать это религиозно.

Обработка:

  • Это, к сожалению, самая сложная часть. Вам нужно убедиться, что каждый раз, когда вы обрабатываете строку UTF-8, вы делаете это безопасно. Самый простой способ сделать это, широко используя PHP mbstring расширение.
  • Строковые операции PHP по умолчанию НЕ безопасны в UTF-8. Есть некоторые вещи, которые вы можете безопасно делать с обычными строковыми операциями PHP (например, конкатенация), но для большинства вещей вы должны использовать эквивалентные mbstring функция.
  • Чтобы знать, что вы делаете (читай: не путайте), вам действительно нужно знать UTF-8 и как он работает на самом низком уровне. Проверьте любую из ссылок с utf8.com для некоторых хороших ресурсов, чтобы узнать все, что вам нужно знать.
  • Кроме того, я чувствую, что об этом нужно сказать где-то, даже если это может показаться очевидным: каждый файл PHP или HTML, который вы будете обслуживать, должен быть закодирован в допустимом UTF-8.

обратите внимание, что вам не нужно использовать utf-8 - важная часть заключается в том, чтобы использовать одну и ту же кодировку везде, независимо от того, какой кодировкой это может быть. но если вам все равно нужно что-то изменить, используйте utf-8.

Я всегда храню проверенные данные с помощью base64_encode(), Сериализованные данные иногда вызывают проблемы, но после использования их значения base64 остаются только простые символы.

Я настоятельно рекомендую вам использовать json_encode вместо сериализации. Однажды вы обнаружите, что пытаетесь использовать эти данные из другого места, не являющегося PHP, и хранение их в JSON делает их читаемыми везде; практически каждый язык поддерживает декодирование JSON и является общепризнанным стандартом.

Ответ об использовании utf8 везде имеет место!:-D

Другие вопросы по тегам