无法将表情符号存储在数据库

时间:2016-09-05 07:58:44

标签: php android ios mysql codeigniter

情况

如果已经提出这个问题,请提前抱歉,但解决方案对我不起作用。

无论我尝试什么,我都无法将表情符号存储在我的数据库中。它们保存为????
正确保存的唯一表情符号只需要3个字节,如害羞的脸或太阳。

实际的utf8mb4无效。

Database screenshot

它已经在Android和Ios上进行了测试。结果相同。

VERSIONS

Mysql:5.5.49
CodeIgniter:3.0.0

THE STEPS

  1. 我修改了数据库字符集和整理属性。

    ALTER DATABASE my_database CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci

  2. 我修改了表格字符集和整理属性。

    ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci

  3. 我已尽可能将表格的每个字段设置为编码:UTF-8(ut8mb4)和整理:utf8mb4_unicode_ci

  4. 我在CodeIgniter应用程序中修改了数据库连接。

  5. 我运行了以下内容:SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci

  6. 最后我也试过这个: REPAIR TABLE table_name; OPTIMIZE TABLE table_name;

  7. 一切都应该设置正确,但它不起作用。

    数据库设置

    这是运行以下命令的结果:

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

    Database settings

    表设置

    表结构的一个screeshot:

    Table settings

    数据库连接

    这些是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。即使它们是分开的数据库,它也可能是一个问题?

    谢谢!

    修改

    这是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');
    

    和其他两个类似的和

    他们被插入表中没有问题:

    enter image description here

    但在实际应用中我真正看到的是:?(这次只有一个?而不是4个)

7 个答案:

答案 0 :(得分:2)

好的,我终于成功了! 感谢所有试图帮助我的人,特别是@Rick James和@Gerard Roche。

<强>建议:

如果您需要使用表情符号首先在localhost上进行简单的测试。创建一个新数据库并制作一个新的应用程序用于测试目的。

如果您按照我在问题中所写的步骤操作,或者您遵循本教程:https://mathiasbynens.be/notes/mysql-utf8mb4#utf8-to-utf8mb4它必须有效。

在新的基本应用程序上本地工作,您将拥有更多的控制权和更多空间来进行所需的所有测试。

<强> SOLUTION:

在我的情况下,问题在于CodeIgniter中数据库的配置。它没有正确设置char_set和coling俯视的排序规则:我覆盖了保存消息的函数中的数据库设置,以确保它正在使用移动数据库。

<强> BEFORE:

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       
}

<强> AFTER:

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

    // other code to save message
}

<强>结论:

应用必须正确设置与数据库的连接。 如果您正确设置了数据库,但未与应用程序建立正确的连接,则无法正常工作。

因此,如果您遇到类似问题,请确保api正确设置char_setutf8mb4db_collatutf8mb4_unicode_ci

答案 1 :(得分:1)

首先加载

my.cnf,然后加载conf.d/*.cnf

不是修改my.cnf *(可能被conf.d/*.cnf中的配置覆盖),而是创建自定义覆盖配置,例如conf.d/90-my.cnf

前缀90可确保最后加载自定义设置,这意味着它们会覆盖任何先前设置的设置。

要确保重新加载新配置,请参阅Reload Without Restarting the MySQL service

示例配置结构(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

答案 2 :(得分:1)

我知道为表情符号获取????的唯一方法是不要将声明为utf8mb4。我知道您显然已确定该列已声明,但请运行SHOW CREATE TABLE table_name;以进一步确认。

如果列覆盖CHARACTER SET,则系统默认值,数据库默认值和表默认值无关。

所有其他尝试答案的注释:COLLATION无关紧要,只有CHARACTER SET与此问题相关

答案 3 :(得分:0)

您可以将表格字段值更改为utf8mb4

,而不是varchar

确保您的所有表格和#39;默认字符集和文本字段转换为utf8mb4,此外还设置客户端&amp;服务器字符集,例如ALTER TABLE mytable charset=utf8mb4, MODIFY COLUMN textfield1 VARCHAR(255) CHARACTER SET utf8mb4,MODIFY COLUMN textfield2 VARCHAR(255) CHARACTER SET utf8mb4;等等。

答案 4 :(得分:0)

您好我在 android 中使用了 EMOJI ,并使用 EMOJI_INDEX orm数据库 >。我在正常消息中以字符串形式保存在数据库中但是当我得到那个时间我检查是否有任何表情符号然后将其转换为那里processemoji。

System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)

从这里看看我如何改变Emoji_Index进行处理

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

有关详细信息,请查看here。 谢谢希望这会对你有所帮助。

答案 5 :(得分:0)

我在Linux上遇到了服务器版本的问题。我不得不手动更改文件database_interface.lib.php

  

if(!PMA_DRIZZLE){           if(!empty($ GLOBALS ['collat​​ion_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
        );
    }
}

答案 6 :(得分:-2)

更新回答

您可以尝试使用字符集utf8排序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将作为代码存储,并在Android和iOS应用中再次转换为emojis。我也在我的项目中使用过这段代码。