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.