Skip to content

Detectando Mensagens com Apenas Emojis em PHP ​

Introdução ​

Ao construir chatbots ou aplicações de mensagens, frequentemente você precisará detectar quando um usuário envia uma mensagem que contém apenas emojis. Isso é comum em cenários como:

  • Reações a stories do Instagram - Usuários frequentemente respondem apenas com "❤️" ou "😂"
  • Reações em chats - Respostas rápidas com emoji como "👍" ou "🔥"
  • Filtragem de mensagens - Tratar mensagens apenas com emojis de forma diferente do texto

Neste artigo, vamos construir uma função simples em PHP para detectar mensagens que contêm apenas emojis usando expressões regulares.

O Desafio do Unicode ​

Emojis são mais complexos do que aparentam. O que parece ser um único emoji pode na verdade ser múltiplos caracteres Unicode combinados:

  • Emojis básicos: Pontos de código únicos como 😀 (U+1F600)
  • Modificadores de tom de pele: 👋🏽 é 👋 + 🏽 (tom de pele médio)
  • Sequências ZWJ: 👨‍👩‍👧 é na verdade 👨 + ZWJ + 👩 + ZWJ + 👧
  • Emojis de bandeiras: 🇧🇷 é formado por dois símbolos indicadores regionais

Essa complexidade significa que não podemos simplesmente verificar um único caractere—precisamos de um padrão regex que cubra todos os intervalos Unicode de emojis.

A Implementação ​

Aqui está uma implementação prática que lida com os emojis mais comuns:

php
/**
 * Verifica se o texto contém apenas emojis e espaços em branco.
 * Útil para detectar reações ou mensagens apenas com emojis.
 */
function isOnlyEmojis(?string $text): bool
{
    if (!$text || trim($text) === '') {
        return false;
    }

    // Remove todos os espaços em branco
    $textWithoutWhitespace = preg_replace('/\s+/u', '', $text);

    if ($textWithoutWhitespace === '') {
        return false;
    }

    // Padrão regex Unicode para emojis
    $emojiPattern = '/^[\x{1F600}-\x{1F64F}' .  // Emoticons
        '\x{1F300}-\x{1F5FF}' .  // Símbolos e Pictogramas Diversos
        '\x{1F680}-\x{1F6FF}' .  // Transporte e Mapa
        '\x{1F700}-\x{1F77F}' .  // Símbolos Alquímicos
        '\x{1F780}-\x{1F7FF}' .  // Formas Geométricas Estendidas
        '\x{1F800}-\x{1F8FF}' .  // Setas Suplementares-C
        '\x{1F900}-\x{1F9FF}' .  // Símbolos e Pictogramas Suplementares
        '\x{1FA00}-\x{1FA6F}' .  // Símbolos de Xadrez
        '\x{1FA70}-\x{1FAFF}' .  // Símbolos e Pictogramas Estendidos-A
        '\x{1F1E6}-\x{1F1FF}' .  // Bandeiras (Símbolos Indicadores Regionais)
        '\x{2600}-\x{26FF}' .    // Símbolos diversos (sol, lua, estrelas)
        '\x{2700}-\x{27BF}' .    // Dingbats
        '\x{2300}-\x{23FF}' .    // Técnicos Diversos
        '\x{2B50}\x{2B55}' .     // Estrela e círculo
        '\x{231A}\x{231B}' .     // Relógio e ampulheta
        '\x{2328}' .             // Teclado
        '\x{23CF}' .             // Símbolo de ejetar
        '\x{23E9}-\x{23F3}' .    // Símbolos de controle de mídia
        '\x{23F8}-\x{23FA}' .    // Símbolos de controle de mídia
        '\x{24C2}' .             // M circulado
        '\x{25AA}\x{25AB}' .     // Quadrados pequenos
        '\x{25B6}\x{25C0}' .     // Botões de play
        '\x{25FB}-\x{25FE}' .    // Quadrados
        '\x{2934}\x{2935}' .     // Setas
        '\x{2B05}-\x{2B07}' .    // Setas
        '\x{3030}' .             // Traço ondulado
        '\x{303D}' .             // Marca de alternação de parte
        '\x{3297}' .             // Ideograma circulado de Parabéns
        '\x{3299}' .             // Ideograma circulado de Secreto
        '\x{FE0F}' .             // Seletor de Variação-16 (apresentação emoji)
        '\x{200D}' .             // Zero Width Joiner (para emojis combinados)
        ']+$/u';

    return preg_match($emojiPattern, $textWithoutWhitespace) === 1;
}

Exemplos de Uso ​

php
// Emojis básicos
isOnlyEmojis('😀');           // true
isOnlyEmojis('❤️🔥');         // true
isOnlyEmojis('👍👍👍');       // true

// Com espaços em branco (ainda válido)
isOnlyEmojis('😀 😂 🎉');     // true

// Emojis combinados (sequências ZWJ)
isOnlyEmojis('👨‍👩‍👧');         // true
isOnlyEmojis('👋🏽');          // true (modificador de tom de pele)

// Conteúdo misto (não é apenas emoji)
isOnlyEmojis('Olá 👋');       // false
isOnlyEmojis('Legal! 🔥');    // false
isOnlyEmojis('123');          // false

// Casos extremos
isOnlyEmojis('');             // false
isOnlyEmojis(null);           // false
isOnlyEmojis('   ');          // false (apenas espaços em branco)

Entendendo os Intervalos Unicode ​

Vamos detalhar os principais intervalos Unicode no nosso padrão:

IntervaloDescriçãoExemplos
1F600-1F64FEmoticons😀 😂 😍 🙄
1F300-1F5FFSímbolos e Pictogramas Diversos🌟 🎉 🔥 💡
1F680-1F6FFTransporte e Mapa🚀 ✈️ 🏠
1F900-1F9FFSímbolos Suplementares🤖 🦄 🧠
1F1E6-1F1FFIndicadores Regionais🇺🇸 🇪🇸 🇧🇷
2600-26FFSímbolos Diversos☀️ ⭐ ♥️
FE0FSeletor de VariaçãoFaz símbolos de texto aparecerem como emoji
200DZero Width JoinerConecta emojis (👨‍👩‍👧)

Por que incluir FE0F e 200D?

O Seletor de Variação-16 (U+FE0F) diz ao sistema para renderizar um caractere como emoji. O Zero Width Joiner (U+200D) conecta múltiplos emojis em um emoji combinado, como emojis de família ou profissão.

Caso de Uso Prático: Reações em Chatbot ​

Veja como você pode usar isso em um contexto de chatbot:

php
function handleIncomingMessage(string $message): void
{
    if (isOnlyEmojis($message)) {
        // É uma reação! Trate de forma diferente
        logReaction($message);
        // Talvez não dispare uma resposta completa de IA para apenas "👍"
        return;
    }

    // Processe como uma mensagem de texto normal
    processTextMessage($message);
}

Limitações ​

Esta abordagem baseada em regex tem algumas limitações:

  1. Novos emojis: O Unicode adiciona novos emojis regularmente. O padrão pode não cobrir as adições mais recentes.
  2. Alguns casos extremos: Certas combinações de emojis raramente usadas podem não ser detectadas.
  3. Performance: Para strings muito longas, regex pode ser mais lento que abordagens baseadas em bibliotecas.

Alternativa: Usando uma Biblioteca ​

Para detecção de emojis mais abrangente, considere usar uma biblioteca dedicada como p3k/emoji-detector:

bash
composer require p3k/emoji-detector
php
use Emoji\Detector;

$detector = new Detector();
$result = $detector->detect('Olá 👋 Mundo');

// Retorna array de emojis detectados com posições

A abordagem com biblioteca é mais robusta, mas adiciona uma dependência. Para verificações simples de "isso é apenas emoji?", a abordagem com regex é leve e suficiente.

Conclusão ​

Detectar mensagens com apenas emojis é útil para muitas aplicações de mensagens. Os pontos principais são:

  1. Emojis são complexos - Podem ser caracteres únicos ou combinações
  2. Use intervalos Unicode - Cubra os principais blocos de emoji no seu regex
  3. Não esqueça ZWJ e FE0F - Esses caracteres invisíveis são essenciais para emojis combinados
  4. Considere seu caso de uso - Regex simples funciona para a maioria dos casos; use uma biblioteca para necessidades avançadas

A abordagem com regex mostrada aqui lida com a grande maioria do uso real de emojis enquanto mantém seu código livre de dependências.