Можно заставить смайлы отображаться на PHP с MySQL 5.x, но не с 8.x

У меня есть проект PHP 7.3, который в настоящее время использует MySQL 5.5 с таблицами utf8. Некоторые таблицы содержат данные смайликов, которые отлично отображаются в текущем проекте. Я пытаюсь обновить проект до MySQL 8.x, но когда я это делаю, данные смайликов отображаются неправильно.

Сначала я обновил все таблицы 5.5 для использования uf8mb4. В этом состоянии данные появились. Затем я обновился до 5.7, и все продолжало работать. Я сбросил эти данные, обновил их до версии 8.0 и перезагрузил (я использовал флаг --default-character-set=utf8mb4 как при дампе, так и при загрузке), а затем данные перестали отображаться правильно, например, лампочка отображалась как 💡.

Я запускаю каждую из этих служб в докере. Мне удалось без проблем выполнить обновление с версии 5.5 до 5.7, используя тот же объем данных, но при попытке обновления с версии 5.7 до 8.0 возникли ошибки, которые я не смог устранить, и в итоге я выполнил дамп/восстановление данных.

Пример таблицы с полем со смайлом:

DROP TABLE IF EXISTS `forums`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `forums` (
  `forumID` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
  `description` text COLLATE utf8_unicode_ci,
  `forumType` varchar(1) COLLATE utf8_unicode_ci DEFAULT 'f',
  `parentID` int(11) DEFAULT NULL,
  `heritage` varchar(25) COLLATE utf8_unicode_ci NOT NULL,
  `order` int(5) NOT NULL,
  `gameID` int(11) DEFAULT NULL,
  `threadCount` int(11) NOT NULL,
  PRIMARY KEY (`forumID`),
  UNIQUE KEY `heritage` (`heritage`),
  KEY `parentID` (`parentID`)
) ENGINE=MyISAM AUTO_INCREMENT=11551 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `forums`
--

LOCK TABLES `forums` WRITE;
/*!40000 ALTER TABLE `forums` DISABLE KEYS */;
INSERT INTO `forums` VALUES (8003,'💡 Gamers\' Plane development',NULL,'f',2,'0002-8003',3180,3181,4);
/*!40000 ALTER TABLE `forums` ENABLE KEYS */;
UNLOCK TABLES;

Чтобы обновить таблицу до utf8mb4, я сделал

ALTER TABLE forums CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Как я тестирую возврат этих данных:

<?php
$mysql = new PDO("mysql:host=mysql;dbname=gamersplane", 'gamersplane', 'mypass');
$mysql->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$mysql->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$forum = $mysql->query('select * from forums where forumID = 8003')->fetch();
?>
<html>
<header>
        <meta http-equiv = "Content-Type" content = "text/html; charset=UTF-8">
</header>
<body>
<?php print_r($forum['title']); ?>
</body>
</html>

Я прочитал [UTF-8 полностью][1] и

[1]: UTF-8 полностью и

  • я использую utf8mb4 в базе данных
  • есть charset=utf8mb4 в моей строке PDO
  • Я явно установил default_charset в моем php.ini, а также попытался установить его во время выполнения
  • попробовали Content-Type: text/html; charset=utf-8 в качестве заголовка PHP, а также метатега HTML

Я сомневаюсь в вашем утверждении о кодировке. Обычно это происходит при изменении кодировки/сопоставления, а не при смене версий. Сопоставление вашего дампа также может быть неправильным. Но шанс очень мал, это как-то связано с версиями.

Wimanicesir 30.08.2024 16:40

дикая догадка, при сбросе/восстановлении данных используйте --default-character-set=utf8mb4? Проверьте в БД, как оно уже сохранено

Abdulla Nilam 30.08.2024 16:42

Виманичесир Вы сомневаетесь в моем утверждении? Что я получу, лежа здесь? Возможно, мне не хватает информации, я не сомневаюсь, но я предоставил шаги, которые я выполнил, чтобы кто-то мог сказать мне, что я делаю неправильно, или попросить предоставить информацию, которую я не знал.

Rohit 30.08.2024 16:44

Абдулла Нилам Спасибо, и да, я использовал флаг набора символов по умолчанию. Я обновлю вопрос, чтобы отразить эту информацию.

Rohit 30.08.2024 16:45

Добавьте сюда свой код. Это привлечет больше пользователей к вопросу

Abdulla Nilam 30.08.2024 16:47

Абдулла Нилам. Я полагаю, вы имели в виду встроенный вопрос, а не суть? Если да, то готово.

Rohit 30.08.2024 16:51
you doubt my claim...никто не думает, что вы врете специально, но многие вопросы здесь возникают из-за того, что люди делают предположения, которые не проверяют, или допускают ошибку при анализе своего кода или данных - мы все делаем это время от времени если мы честны. Поэтому нам просто хотелось бы увидеть некоторые доказательства этих вещей, если мы можем, особенно когда кто-то делает утверждение, которое звучит удивительно или маловероятно. Тогда нам будет легче исключить или исключить возможные причины проблемы :-)
ADyson 30.08.2024 16:54

P.S. Ваше полное руководство по таким проблемам обычно UTF-8 до конца. Я не на 100% уверен, что этот пост является прямым дубликатом предыдущего, но я был бы удивлен, если бы в нем не было ничего релевантного.

ADyson 30.08.2024 16:58

ADyson Я полностью понимаю, что люди делают ошибки, но именно поэтому я предоставил код с самого начала. Как вы сказали, мы все совершаем ошибки, но если вы в них погрязли, то часто этого не замечаете. Начальное утверждение типа I'm doubting your claim оскорбительно и не помогает понять, идиот ли я или нужна дополнительная информация. И я прочитал сообщение UTF-8, оно упоминалось в предыдущем вопросе, который я плохо сформулировал. Я все сделал там, поэтому предоставил код здесь.

Rohit 30.08.2024 17:17

ADyson Я обновил вопрос, указав все шаги из руководства UTF-8, которое я предпринял.

Rohit 30.08.2024 17:28
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
10
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Кодирование в базах данных — это всегда очень весело! К сожалению, когда вы меняете набор символов, он не обновляет данные, а только то, как база данных интерпретирует данные, а MySQL не выполняет изменение кодировки «на лету» и всегда записывает байты по мере их поступления от клиента. Из примера вы можете видеть, что 💡 — это latin1 представление 💡, и когда вы выгружаете данные, он выгружает их уже в неправильной кодировке.

Чтобы проверить проблему, вы можете попытаться преобразовать данные с помощью запроса:

SELECT
  CONVERT(BINARY(CONVERT(title USING latin1)) USING utf8mb4)
FROM forums 
WHERE id = 8003;

в вашей последней среде MySQL8 эмодзи должны отображаться правильно. Если это так, вам следует попытаться снова сбросить данные, и на этот раз использовать кодировку, в которой они были закодированы изначально, скорее всего, latin1 с использованием --default-character-set=latin1. Файл дампа должен содержать смайлы вместо текста в виде 💡.

Имейте в виду, что если у вас есть новый контент в таблице, он будет дважды закодирован или заполнение дампа не удастся. Если новый текст несовместим с кодировкой latin1, лучше сделать это с исходным набором, если у вас все еще есть доступ к нему.

Потрясающий! Я могу написать сценарий, который преобразует исходные данные. Я думаю, что сейчас одна путаница заключается в том, что база данных всегда была uft8, так почему же данные имеют латиницу1? Что я здесь не понимаю?

Rohit 30.08.2024 19:37

Похоже, это сработало. Поменял на обновление и на тестовом сайте появились смайлы. Это странно, потому что сайт был в UTF8 с момента его создания, и изначально я попробовал сделать дамп на latin1 с восстановлением с использованием utf8mb4, и это не сработало.

Rohit 31.08.2024 14:18

Когда данные записываются в MySQL, они записываются с использованием кодировки соединения, которая часто не указывается, и используются настройки сервера по умолчанию. Для MySQL 5.7 и более ранних версий по умолчанию используется latin1, начиная с версии 8.0 — utf8mb4. Чтобы гарантировать ожидаемое кодирование, вы можете указать его на уровне соединения, например. mysql:host=mysql;dbname=gamersplane;charset=utf8mb4.

qshurick 31.08.2024 23:53

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