Detectar Mensajes con Solo Emojis en PHP
Introducción
Al construir chatbots o aplicaciones de mensajería, frecuentemente necesitarás detectar cuando un usuario envía un mensaje que contiene solo emojis. Esto es común en escenarios como:
- Reacciones a stories de Instagram - Los usuarios frecuentemente responden solo con "❤️" o "😂"
- Reacciones en chats - Respuestas rápidas con emoji como "👍" o "🔥"
- Filtrado de mensajes - Tratar mensajes con solo emojis de forma diferente al texto
En este artículo, construiremos una función simple en PHP para detectar mensajes que contienen solo emojis usando expresiones regulares.
El Desafío del Unicode
Los emojis son más complejos de lo que aparentan. Lo que parece ser un único emoji puede en realidad ser múltiples caracteres Unicode combinados:
- Emojis básicos: Puntos de código únicos como 😀 (U+1F600)
- Modificadores de tono de piel: 👋🏽 es 👋 + 🏽 (tono de piel medio)
- Secuencias ZWJ: 👨👩👧 es en realidad 👨 + ZWJ + 👩 + ZWJ + 👧
- Emojis de banderas: 🇲🇽 está formado por dos símbolos indicadores regionales
Esta complejidad significa que no podemos simplemente verificar un único carácter—necesitamos un patrón regex que cubra todos los rangos Unicode de emojis.
La Implementación
Aquí hay una implementación práctica que maneja los emojis más comunes:
/**
* Verifica si el texto contiene solo emojis y espacios en blanco.
* Útil para detectar reacciones o mensajes con solo emojis.
*/
function isOnlyEmojis(?string $text): bool
{
if (!$text || trim($text) === '') {
return false;
}
// Eliminar todos los espacios en blanco
$textWithoutWhitespace = preg_replace('/\s+/u', '', $text);
if ($textWithoutWhitespace === '') {
return false;
}
// Patrón regex Unicode para emojis
$emojiPattern = '/^[\x{1F600}-\x{1F64F}' . // Emoticones
'\x{1F300}-\x{1F5FF}' . // Símbolos y Pictogramas Diversos
'\x{1F680}-\x{1F6FF}' . // Transporte y Mapa
'\x{1F700}-\x{1F77F}' . // Símbolos Alquímicos
'\x{1F780}-\x{1F7FF}' . // Formas Geométricas Extendidas
'\x{1F800}-\x{1F8FF}' . // Flechas Suplementarias-C
'\x{1F900}-\x{1F9FF}' . // Símbolos y Pictogramas Suplementarios
'\x{1FA00}-\x{1FA6F}' . // Símbolos de Ajedrez
'\x{1FA70}-\x{1FAFF}' . // Símbolos y Pictogramas Extendidos-A
'\x{1F1E6}-\x{1F1FF}' . // Banderas (Símbolos Indicadores Regionales)
'\x{2600}-\x{26FF}' . // Símbolos diversos (sol, luna, estrellas)
'\x{2700}-\x{27BF}' . // Dingbats
'\x{2300}-\x{23FF}' . // Técnicos Diversos
'\x{2B50}\x{2B55}' . // Estrella y círculo
'\x{231A}\x{231B}' . // Reloj y reloj de arena
'\x{2328}' . // Teclado
'\x{23CF}' . // Símbolo de expulsar
'\x{23E9}-\x{23F3}' . // Símbolos de control de medios
'\x{23F8}-\x{23FA}' . // Símbolos de control de medios
'\x{24C2}' . // M en círculo
'\x{25AA}\x{25AB}' . // Cuadrados pequeños
'\x{25B6}\x{25C0}' . // Botones de reproducir
'\x{25FB}-\x{25FE}' . // Cuadrados
'\x{2934}\x{2935}' . // Flechas
'\x{2B05}-\x{2B07}' . // Flechas
'\x{3030}' . // Guión ondulado
'\x{303D}' . // Marca de alternancia de parte
'\x{3297}' . // Ideograma en círculo de Felicitaciones
'\x{3299}' . // Ideograma en círculo de Secreto
'\x{FE0F}' . // Selector de Variación-16 (presentación emoji)
'\x{200D}' . // Zero Width Joiner (para emojis combinados)
']+$/u';
return preg_match($emojiPattern, $textWithoutWhitespace) === 1;
}Ejemplos de Uso
// Emojis básicos
isOnlyEmojis('😀'); // true
isOnlyEmojis('❤️🔥'); // true
isOnlyEmojis('👍👍👍'); // true
// Con espacios en blanco (aún válido)
isOnlyEmojis('😀 😂 🎉'); // true
// Emojis combinados (secuencias ZWJ)
isOnlyEmojis('👨👩👧'); // true
isOnlyEmojis('👋🏽'); // true (modificador de tono de piel)
// Contenido mixto (no es solo emoji)
isOnlyEmojis('Hola 👋'); // false
isOnlyEmojis('Genial! 🔥'); // false
isOnlyEmojis('123'); // false
// Casos extremos
isOnlyEmojis(''); // false
isOnlyEmojis(null); // false
isOnlyEmojis(' '); // false (solo espacios en blanco)Entendiendo los Rangos Unicode
Desglosemos los principales rangos Unicode en nuestro patrón:
| Rango | Descripción | Ejemplos |
|---|---|---|
1F600-1F64F | Emoticones | 😀 😂 😍 🙄 |
1F300-1F5FF | Símbolos y Pictogramas Diversos | 🌟 🎉 🔥 💡 |
1F680-1F6FF | Transporte y Mapa | 🚀 ✈️ 🏠 |
1F900-1F9FF | Símbolos Suplementarios | 🤖 🦄 🧠 |
1F1E6-1F1FF | Indicadores Regionales | 🇺🇸 🇪🇸 🇲🇽 |
2600-26FF | Símbolos Diversos | ☀️ ⭐ ♥️ |
FE0F | Selector de Variación | Hace que símbolos de texto aparezcan como emoji |
200D | Zero Width Joiner | Conecta emojis (👨👩👧) |
¿Por qué incluir FE0F y 200D?
El Selector de Variación-16 (U+FE0F) le indica al sistema que renderice un carácter como emoji. El Zero Width Joiner (U+200D) conecta múltiples emojis en un emoji combinado, como emojis de familia o profesión.
Caso de Uso Práctico: Reacciones en Chatbot
Así es como podrías usar esto en un contexto de chatbot:
function handleIncomingMessage(string $message): void
{
if (isOnlyEmojis($message)) {
// Es una reacción! Manejar de forma diferente
logReaction($message);
// Tal vez no disparar una respuesta completa de IA para solo "👍"
return;
}
// Procesar como un mensaje de texto normal
processTextMessage($message);
}Limitaciones
Este enfoque basado en regex tiene algunas limitaciones:
- Nuevos emojis: Unicode agrega nuevos emojis regularmente. El patrón puede no cubrir las adiciones más recientes.
- Algunos casos extremos: Ciertas combinaciones de emojis poco usadas pueden no ser detectadas.
- Rendimiento: Para strings muy largos, regex puede ser más lento que enfoques basados en bibliotecas.
Alternativa: Usando una Biblioteca
Para detección de emojis más completa, considera usar una biblioteca dedicada como p3k/emoji-detector:
composer require p3k/emoji-detectoruse Emoji\Detector;
$detector = new Detector();
$result = $detector->detect('Hola 👋 Mundo');
// Retorna array de emojis detectados con posicionesEl enfoque con biblioteca es más robusto, pero agrega una dependencia. Para verificaciones simples de "¿esto es solo emoji?", el enfoque con regex es ligero y suficiente.
Conclusión
Detectar mensajes con solo emojis es útil para muchas aplicaciones de mensajería. Los puntos clave son:
- Los emojis son complejos - Pueden ser caracteres únicos o combinaciones
- Usa rangos Unicode - Cubre los principales bloques de emoji en tu regex
- No olvides ZWJ y FE0F - Estos caracteres invisibles son esenciales para emojis combinados
- Considera tu caso de uso - Regex simple funciona para la mayoría de los casos; usa una biblioteca para necesidades avanzadas
El enfoque con regex mostrado aquí maneja la gran mayoría del uso real de emojis mientras mantiene tu código libre de dependencias.

