Не удается сохранить emoji в базе данных

СИТУАЦИЯ:

Извините, если этот вопрос уже задан, но решения для меня не работают.

Независимо от того, что я пытаюсь, я не могу хранить emoji в моей базе данных. Они сохраняются как ????.

Единственные emojis, которые были правильно сохранены, - это те, которые требуют только 3 байта, например, застенчивое лицо или солнце.

Фактический utf8mb4 не работает.

Снимок базы данных

Он был протестирован как на Android, так и на Ios. С такими же результатами.

ВЕРСИИ

Mysql: 5.5.49
CodeIgniter: 3.0.0

ШАГИ:

  • Я изменил набор символов базы данных и свойства сопоставления.

    ALTER DATABASE my_database CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci

  • Я изменил настройки набора символов и свойства сопоставления.

    ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci

  • Я установил каждое поле таблицы, где это возможно, в качестве Кодировки: UTF-8(ut8mb4) и Collation: utf8mb4_unicode_ci

  • Я изменил соединение с базой данных в приложении CodeIgniter.

  • Я выполнил следующее: SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci

  • Наконец, я также пробовал это: REPAIR TABLE table_name; OPTIMIZE TABLE table_name;

Все должно быть настроено правильно, но все же оно не работает.

НАСТРОЙКИ БАЗА ДАННЫХ:

Это результат выполнения следующей команды:

`SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';`

Настройки базы данных

НАСТРОЙКИ ТАБЛИЦЫ:

Сводка таблицы структуры таблицы:

Настройки таблицы

ПОДКЛЮЧЕНИЕ БАЗЫ ДАННЫХ:

Это настройки подключения базы данных в файле database.php(обратите внимание, что это не единственная база данных, есть и другие, которые подключаются с помощью utf8)

$db['my_database'] = array(
        'dsn'           => '',
        'hostname'      => PROJECT_DATABASE_HOSTNAME,
        'username'      => PROJECT_DATABASE_USERNAME,
        'password'      => PROJECT_DATABASE_PASSWORD,
        'database'      => PROJECT_DATABASE_NAME,
        'dbdriver'      => 'mysqli',
        'dbprefix'      => '',
        'pconnect'      => FALSE,
        'db_debug'      => TRUE,
        'cache_on'      => FALSE,
        'cachedir'      => '',
        'char_set'      => 'utf8mb4',
        'dbcollat'      => 'utf8mb4_unicode_ci',
        'swap_pre'      => '',
        'encrypt'       => FALSE,
        'compress'      => FALSE,
        'stricton'      => FALSE,
        'failover'      => array(),
        'save_queries'  => TRUE
    );

НАСТРОЙКИ MY.CNF:

Это все содержимое файла my.cnf:

[mysqld]
default-storage-engine=MyISAM
innodb_file_per_table=1
max_allowed_packet=268435456
open_files_limit=10000
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

ВОПРОС:

Вы знаете, почему это не работает? Я что-то пропустил?

HYPHOTESIS 1:

Я не уверен, но причиной проблемы может быть следующее:

Как вы можете видеть в my.cnf character-set-server, явно указано как utf8mb4:

Но после запуска запроса в базе данных:

SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';

В результате character-set-server = latin1

Знаете ли вы, почему? Почему на самом деле не обновляется?

HYPHOTESIS 2:

Приложение использует несколько разных баз данных. Этот параметр установлен в utf8mb4, но все остальные установлены в utf8. Это может быть проблемой, даже если они разделены базы данных?

Спасибо!

EDIT:

Это результат SHOW CREATE TABLE app_messages;

CREATE TABLE `app_messages` (
  `message_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `project_id` bigint(20) NOT NULL,
  `sender_id` bigint(20) NOT NULL,
  `receiver_id` bigint(20) NOT NULL,
  `message` text COLLATE utf8mb4_unicode_ci,
  `timestamp` bigint(20) DEFAULT NULL,
  `is_read` enum('x','') COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`message_id`)
) ENGINE=InnoDB AUTO_INCREMENT=496 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

ИЗМЕНИТЬ 2:

Я выполнил следующую команду:

INSERT INTO app_messages (message_id, project_id, sender_id, receiver_id, message, timestamp, is_read)
VALUES ('496','322','77','188', '😜' ,'1473413606','x');

И другие два аналогичные с 😂 и 👻

Они были вставлены в таблицу без проблем:

введите описание изображения здесь

Но в самом приложении я действительно вижу: ? (на этот раз только один, а не 4)

Ответ 1

Хорошо, наконец, мне удалось заставить его работать! Спасибо всем, кто пытался мне помочь, особенно @Rick James и @Gerard Roche.

SUGGESTION:

Если вам нужно работать с emoji, сначала сделайте простые тесты на localhost. Создайте новую базу данных и создайте новое приложение для тестирования.

Если вы выполните шаги, которые я написал в вопросе, или если вы следуете этому руководству: https://mathiasbynens.be/notes/mysql-utf8mb4#utf8-to-utf8mb4, он должен работать.

Работая локально в новом базовом приложении, у вас будет больше контроля и больше места, чтобы выполнить все необходимые вам тесты.

РЕШЕНИЕ:

В моем случае проблема заключалась в настройке базы данных в CodeIgniter. Это была неправильная настройка char_set и сортировки для глупого игнорирования: я переопределял настройки базы данных в функции, которая сохраняет сообщения, чтобы убедиться, что она работает с базой данных для мобильных устройств.

ДО:

function message_save ( $data = FALSE )
{   
    $project_db_config                  = array();
    $project_db_config['hostname']      = 'MY_HOST';
    $project_db_config['username']      = 'MY_USERNAME';
    $project_db_config['password']      = 'MY_PASSWORD';
    $project_db_config['database']      = 'MY_DATABASE';

    $mobile_db                          = $this->load->database( $project_db_config, TRUE );

    // other code to save message       
}

ПОСЛЕ:

function message_save ( $data = FALSE )
{
    $mobile_db_connection = $this->load->database('admin_mobile_mh', TRUE);

    // other code to save message
}

ВЫВОД:

Приложение должно правильно установить соединение с базой данных. Если вы правильно настроили базу данных, но вы не устанавливаете правильное соединение с вашим приложением, это не сработает.

Итак, если вы столкнулись с подобными проблемами, убедитесь, что api правильно настроил char_set как utf8mb4 и db_collat как utf8mb4_unicode_ci.

Ответ 2

Сначала загружается

my.cnf, затем conf.d/*.cnf.

Вместо изменения my.cnf * (который может быть переопределен конфигурациями в conf.d/*.cnf), создайте настраиваемую конфигурацию переопределения, например. conf.d/90-my.cnf.

Префикс 90 гарантирует, что пользовательские настройки будут загружены последним, что означает, что они перезаписывают ранее установленные настройки.

Чтобы перезагрузить новую конфигурацию, см. Перезагрузка без перезагрузки службы MySQL.

Пример структуры конфигурации (Linux)

.
├── conf.d
│   ├── 90-my.cnf
│   ├── conn.cnf
│   ├── my5.6.cnf
│   └── mysqld_safe_syslog.cnf
├── debian.cnf
├── debian-start
└── my.cnf

conf.d/90-my.cnf

# https://mathiasbynens.be/notes/mysql-utf8mb4
# http://stackoverflow.com/q/3513773/934739

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]

character-set-client-handshake = FALSE

# The server character set and collation are used as default values if the
# database character set and collation are not specified in CREATE DATABASE
# statements. They have no other purpose.
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

Ответ 3

Единственный способ получить ???? для Emoji - не иметь объявленного столбца utf8mb4. Я понимаю, что вы, по-видимому, определили, что столбец объявлен таким образом, но, пожалуйста, запустите SHOW CREATE TABLE table_name;, чтобы подтвердить его.

По умолчанию система, база данных по умолчанию и значение по умолчанию не имеют значения, если столбец переопределяет CHARACTER SET.

Замечание ко всем остальным попыткам ответов: COLLATION не имеет значения, для этого вопроса применим только CHARACTER SET.

Ответ 4

Вместо varchar вы можете изменить значение, указанное в таблице, следующим образом: utf8mb4

Убедитесь, что все стандартные символы и текстовые поля ваших таблиц преобразуются в utf8mb4, в дополнение к настройке наборов символов клиента и сервера, например. ALTER TABLE mytable charset=utf8mb4, MODIFY COLUMN textfield1 VARCHAR(255) CHARACTER SET utf8mb4,MODIFY COLUMN textfield2 VARCHAR(255) CHARACTER SET utf8mb4; и т.д.

Ответ 5

Привет, я использовал EMOJI в android, и я сохранил его в базе данных orm, используя EMOJI_INDEX. Я сохранен в db в обычном сообщении в строковой форме, но когда я получаю это время, я проверяю, есть ли какие-либо emoji, затем преобразуйте его туда processemoji.

textMessage.setText(getItem(pos).file != null ? "":EmojiUtil.getInstance(context).processEmoji(getItem(pos).message, textMessage.getTextSize()));

Посмотрите здесь, как я изменил Emoji_Index для обработки

if (emojiImages == null || emojiImages.isRecycled()) {
        InputStream localInputStream;
        try {
            localInputStream = context.getAssets().open("emoji/emoji_2x.png");
            Options opts = new Options();
            opts.inPurgeable = true;
            opts.inInputShareable = true;
            emojiImages = BitmapFactory.decodeStream(localInputStream, null, opts);
        } catch (IOException e) {
            return Html.fromHtml(paramString);
        }
    }

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

Ответ 6

У меня была проблема с версией сервера, на linux. Мне пришлось изменить файл database_interface.lib.php вручную и вокруг этого

if (! PMA_DRIZZLE) {         if (! empty ($ GLOBALS ['collation_connection'])) {

измените его так, чтобы оно стало следующим: (обратите внимание на ссылки utf8mb4_unicode_ci)

    // Skip charsets for Drizzle
if (!PMA_DRIZZLE) {
    if (! empty($GLOBALS['collation_connection'])) {
        PMA_DBI_query("SET CHARACTER SET 'utf8mb4';", $link, PMA_DBI_QUERY_STORE);
        $set_collation_con_query = "SET collation_connection = '"
            . PMA_Util::sqlAddSlashes($GLOBALS['collation_connection']) . "';";
        PMA_DBI_query(
            $set_collation_con_query,
            $link,
            PMA_DBI_QUERY_STORE
        );
    } else {
        PMA_DBI_query(
            "SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci';",
            $link,
            PMA_DBI_QUERY_STORE
        );
    }
}

Ответ 7

Обновленный ответ

Вы можете попробовать charset utf8 collation utf8_unicode_ci вместо utf8mb4_unicode_ci.

запустите этот запрос

ALTER TABLE table_name CHANGE `column_name` `column_name` TEXT CHARSET utf8 COLLATE utf8_unicode_ci;

старый ответ Вы должны использовать сопоставление utf8mb4_bin вместо utf8mb4_unicode_ci.

запустите этот запрос

 ALTER TABLE table_name CHANGE `column_name` `column_name` TEXT CHARSET utf8mb4 COLLATE utf8mb4_bin;

Emojis будет храниться как код и снова преобразован в emojis в приложениях Android и iOS. Я также использовал этот код в своих проектах.