Буквально вчера, словил не приятную багу.
(P.S. вполне возможно что многие знают об этой баге. Но ради интереса решил воспроизвести данную багу на других сайтах — в 90% случаев ошибка воспроизводится).
Имеется сайт на MODX Revolution 2.7.3 в связке с miniShop2 2.5.0.
Бага заключалась в том, что пришёл «пустой» заказ. Т.е. все реквизиты клиента в письме и заказе есть, а вот товаров в этом заказе нет.
Долго и упорно не мог понять в чём же проблема. Благо есть вебвизор и он таки помог воспроизвести ошибку.
Дело оказалось в смайликах. Которые были вставлены в комментарий к заказу.
Как воспроизвести ошибку:
1. Кладём товар в корзину, идём в оформление заказа, заполняем поля которые надо заполнить и в комментарий к заказу вставляем любой Emoji смайлик.
Например такой: ???????? (как видим, даже данный сайт не поддерживает смайлики)
1.1 Тыкаем в любое место страницы чтобы убрать фокус с поля комментария и жмём на F5.
Убеждаемся что корзина стала пустой и бага таки присутствует =)
Причина данного явления:
1. minishop2 — никак не обрабатывает поле comment. Т.е. сохраняет его «как есть».
2. Все заполненные поля заказа, minishop2 сохраняет в сессию. В том числе и комментарий.
3. MODX дублирует сессию в базу данных. Т.е. каждая сессия — это отдельная запись в базе данных (таблица: modx_session).
4. В 99% случаев, ваша база данных имеет кодировку utf8_general_ci (особо отчаянные имеют кодировку CP1251).
5. Смайлики — это какой-то там 4-х битный набор символов. Данный набор символов поддерживает кодировка utf8mb4_unicode_ci (данную кодировку разработала команда разработчиков MySQL и была специально создана для поддержки смайликов).
6. Если вы сохраните смайлик в базе данных с кодировкой utf8_general_ci, то весь текст который будет идти после смайлика — затрется.
7. Как мы уже знаем, MODX дублирует все сессии в базу. В базу записывается и сессия минишопа. Если в этой записи имеется смайлик — то такая запись 100% «грохнется» и MODX не сможет её прочитать, т.к. текст банально затрется. Если MODX не может прочитать запись — то он обнуляет сессию и создаёт новую запись.
Таким образом мы имеем обнулённую корзину.
Решение проблемы:
Самое минимальное, это нужно сделать следующее:
0. Сделать бэкап базы данных.
1. Открыть базу данных (через phpmyadmin, Navicat и т.п.) и найти таблицу: modx_session (где modx — это ваш префикс).
1.1. В данной таблице необходимо поменять кодировку у поля «data» на utf8mb4_unicode_ci
2. На сервере найти и открыть файл ../core/config/config.inc.php
2.1. И установить кодировку:
9-я строка:
$database_connection_charset = 'utf8mb4';
12-я строка:
$database_dsn = 'mysql:host=localhost;dbname=mydbname;charset=utf8mb4';
Ну а по хорошему, нужно конечно же перевести всю базу в кодировку utf8mb4_unicode_ci
Но и минимальное решение — тоже заработает.
Андрей Казунин 20.08.2020 21:16 #
igor781 08.04.2021 22:55 #
Андрей Казунин 09.04.2021 11:55 #
Вараника 16.09.2020 00:23 #
igor781 08.04.2021 22:57 #
Юлия Климова 30.09.2021 10:27 #
Надеюсь, не часто клиенты эмоджи в комментариях будут пытаться отправить, как-то не очень хочется кодировку БД менять… Точнее, я понимаю, что ее все равно придется менять, но жду, может, какой скрипт кто выложит для поддержки хранения 4-х байтовых символов?..