php - No se puede almacenar emoji en la base de datos
android ios (7)
Bueno, finalmente me las arreglé para hacerlo funcionar! Gracias a todos los que intentaron ayudarme, especialmente @Rick James y @Gerard Roche.
SUGERENCIA:
Si necesitas trabajar con emoji, primero haz pruebas sencillas en localhost. Crea una nueva base de datos y crea una aplicación nueva para propósitos de prueba.
Si sigue los pasos que escribí en la pregunta o si sigue este tutorial: https://mathiasbynens.be/notes/mysql-utf8mb4#utf8-to-utf8mb4 debe funcionar.
Al trabajar localmente en una aplicación básica nueva, tendrá más control y más espacio para realizar todas las pruebas que necesita.
SOLUCIÓN:
En mi caso, el problema estaba en la configuración de la base de datos en CodeIgniter. No estaba configurando correctamente el char_set y la intercalación para una omisión estúpida: estaba anulando la configuración de la base de datos en la función que guarda los mensajes para estar seguro de que estaba funcionando con la base de datos móvil.
ANTES DE:
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
}
DESPUÉS:
function message_save ( $data = FALSE )
{
$mobile_db_connection = $this->load->database(''admin_mobile_mh'', TRUE);
// other code to save message
}
CONCLUSIÓN:
La aplicación debe establecer la conexión a la base de datos correctamente. Si tiene la base de datos correctamente configurada pero no realiza la conexión adecuada con su aplicación, no funcionará.
Entonces, si encuentra problemas similares, asegúrese de que la api configure correctamente char_set
como utf8mb4
y db_collat
como utf8mb4_unicode_ci
.
LA SITUACIÓN :
Lo siento de antemano si esta pregunta ya se ha hecho, pero las soluciones no funcionan para mí.
No importa lo que intente, no puedo almacenar emoji en mi base de datos. Se guardan como ????
.
Los únicos emojis que se guardan correctamente son los que solo requieren 3 bytes, como la cara tímida o el sol.
El utf8mb4 real no está funcionando.
Ha sido probado tanto en Android como en iOS. Con los mismos resultados.
VERSIONES :
Mysql: 5.5.49
CodeIgniter: 3.0.0
LOS PASOS :
He modificado el conjunto de caracteres de la base de datos y las propiedades de colación.
ALTER DATABASE my_database CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci
He modificado el conjunto de caracteres de la tabla y las propiedades de colación.
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
He establecido cada campo de la tabla, donde es posible, como Codificación:
UTF-8(ut8mb4)
y Collation:utf8mb4_unicode_ci
He modificado la conexión de la base de datos en la aplicación CodeIgniter.
He ejecutado lo siguiente:
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci
Por último, también he intentado esto:
REPAIR TABLE table_name; OPTIMIZE TABLE table_name;
REPAIR TABLE table_name; OPTIMIZE TABLE table_name;
Todo debería haberse configurado correctamente, pero aún así no funciona.
CONFIGURACIÓN DE LA BASE DE DATOS :
Este es el resultado ejecutando el siguiente comando:
`SHOW VARIABLES WHERE Variable_name LIKE ''character/_set/_%'' OR Variable_name LIKE ''collation%'';`
CONFIGURACIÓN DE LA MESA :
Un screeshot de la estructura de la mesa:
CONEXIÓN DE LA BASE DE DATOS :
Estas son las configuraciones de conexión de la base de datos dentro de database.php (tenga en cuenta que esta no es la única base de datos, también hay otras que se conectan usando 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
);
AJUSTES DE MY.CNF :
Este es todo el contenido del archivo 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
LA PREGUNTA :
¿Sabes por qué no está funcionando? ¿Me estoy perdiendo de algo?
HYPHOTESIS 1 :
No estoy seguro, pero la causa del problema puede ser esta:
Como se puede ver en my.cnf character-set-server
está claramente configurado como utf8mb4
:
Pero después de ejecutar la consulta en la base de datos:
SHOW VARIABLES WHERE Variable_name LIKE ''character/_set/_%'' OR Variable_name LIKE ''collation%'';
El resultado es que character-set-server = latin1
¿Sabes por qué es eso? ¿Por qué no se está actualizando?
HYPHOTESIS 2 :
La aplicación utiliza varias bases de datos diferentes. Este se establece en utf8mb4 pero todos los demás se establecen en utf8. ¿Puede ser un problema incluso si son bases de datos separadas?
¡Gracias!
EDITAR:
Este es el resultado de 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
EDIT 2:
He ejecutado el siguiente comando:
INSERT INTO app_messages (message_id, project_id, sender_id, receiver_id, message, timestamp, is_read)
VALUES (''496'',''322'',''77'',''188'', ''😜'' ,''1473413606'',''x'');
Y otros dos similares con 😂 y 👻.
Se insertaron en la tabla sin problemas:
Pero en la aplicación real lo que realmente veo es ?
(esta vez solo una? y no 4)
En lugar de varchar puede cambiar el valor archivado de la tabla de la siguiente manera a utf8mb4
Asegúrese de que todos los conjuntos de caracteres y campos de texto predeterminados de sus tablas se conviertan a utf8mb4, además de configurar los conjuntos de caracteres del cliente y del servidor, por ejemplo, ALTER TABLE mytable charset=utf8mb4, MODIFY COLUMN textfield1 VARCHAR(255) CHARACTER SET utf8mb4,MODIFY COLUMN textfield2 VARCHAR(255) CHARACTER SET utf8mb4;
y así.
Hola, he usado EMOJI en Android y lo he almacenado en la base de datos orm usando EMOJI_INDEX . EMOJI_INDEX guardado en db en un mensaje normal en forma de cadena, pero cuando llego ese tiempo, compruebo si hay algún emoji y luego lo convierto en ese proceso.
textMessage.setText(getItem(pos).file != null ? "":EmojiUtil.getInstance(context).processEmoji(getItem(pos).message, textMessage.getTextSize()));
Echa un vistazo desde aquí cómo cambié Emoji_Index para procesar
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);
}
}
Para más información echar un vistazo desde here . Gracias espero que esto te ayude.
La única forma que conozco de conseguir ????
para un Emoji es no tener la columna declarada utf8mb4
. Entiendo que aparentemente has determinado que la columna está declarada de esa manera, pero ejecuta SHOW CREATE TABLE table_name;
para confirmarlo aún más.
El valor predeterminado del sistema, el valor predeterminado de la base de datos y el valor predeterminado de la tabla son irrelevantes si la columna anula el conjunto de CHARACTER SET
.
Una nota a todos los demás intentos de respuesta: la COLLATION
es irrelevante, solo el CHARACTER SET
es relevante para esta pregunta .
Tuve un problema con la versión del servidor, en linux. Tuve que cambiar el archivo database_interface.lib.php manualmente y alrededor de este
if (! PMA_DRIZZLE) {if (! empty ($ GLOBALS [''collation_connection''])) {
cámbielo para que se convierta en esto: (tenga en cuenta las referencias 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
);
}
}
my.cnf
se carga primero, luego conf.d/*.cnf
.
En lugar de modificar my.cnf
* (que puede ser anulado por las configuraciones en conf.d/*.cnf
), cree una configuración de anulación personalizada, por ejemplo, conf.d/90-my.cnf
.
El prefijo 90
asegura que las configuraciones personalizadas se carguen en último lugar, lo que significa que sobrescriben cualquier configuración anterior.
Para asegurarse de que se recargue la nueva configuración, vea Recargar sin reiniciar el servicio MySQL .
Ejemplo de Estructura de Configuración (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://.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
Respuesta actualizada
Puedes probar el conjunto de caracteres utf8
collation utf8_unicode_ci
lugar de utf8mb4_unicode_ci
.
ejecutar esta consulta
ALTER TABLE table_name CHANGE `column_name` `column_name` TEXT CHARSET utf8 COLLATE utf8_unicode_ci;
respuesta antigua Debes usar la intercalación utf8mb4_bin
lugar de utf8mb4_unicode_ci
.
ejecutar esta consulta
ALTER TABLE table_name CHANGE `column_name` `column_name` TEXT CHARSET utf8mb4 COLLATE utf8mb4_bin;
Los emojis se almacenarán como código y se convertirán de nuevo en emojis en las aplicaciones de Android e iOS. También he usado este código en mis proyectos.