Dividindo Mensagens Longas para Redes Sociais: Um Utilitário PHP para Limites de Caracteres
Introdução
Ao construir chatbots, ferramentas para redes sociais ou aplicações com IA, você inevitavelmente enfrentará um desafio comum: o texto que você quer enviar é maior do que a plataforma permite.
DMs do Instagram têm limite de 1.000 caracteres. Twitter/X limita posts a 280 caracteres. Mensagens SMS são divididas em 160 caracteres. E quando você trabalha com respostas geradas por IA, elas raramente respeitam esses limites.
A abordagem ingênua—cortar o texto exatamente no limite de caracteres—resulta em palavras quebradas e mensagens ilegíveis. O que você precisa é uma divisão inteligente que respeite os limites das palavras e produza partes limpas e legíveis.
O Problema
Considere este cenário: seu assistente de IA gera uma resposta de 3.000 caracteres para uma consulta de cliente. Você precisa enviá-la via DM do Instagram (limite de 1.000 caracteres). Simplesmente cortar na posição 1000 pode produzir:
...e a melhor abordagem seria reconfiAo invés de:
...e a melhor abordagem seriaSeus usuários merecem algo melhor.
A Solução
Aqui está uma função utilitária PHP que divide mensagens longas em limites naturais—espaços e quebras de linha—respeitando seu limite de caracteres:
public static function splitMessageByLength(string $message, int $length = 4096): array
{
// Normaliza quebras de linha para \n
$message = str_replace("\r\n", "\n", $message);
$message = str_replace("\r", "\n", $message);
$messages = [];
$current_message = '';
// Percorre a mensagem caractere por caractere
for ($i = 0, $count = mb_strlen($message, 'UTF-8'); $i < $count; $i++) {
$char = mb_substr($message, $i, 1, 'UTF-8');
// Adiciona o caractere
$current_message .= $char;
// Verifica se a mensagem atual excede o limite
if (mb_strlen($current_message, 'UTF-8') >= $length) {
// Encontra a última ocorrência de espaço ou quebra de linha
$lastSpace = mb_strrpos($current_message, ' ', 0, 'UTF-8');
$lastBreak = mb_strrpos($current_message, "\n", 0, 'UTF-8');
// Determina a posição de corte (prefere quebra de linha sobre espaço)
$splitPos = $lastBreak !== false ? $lastBreak : $lastSpace;
// Se não houver espaço ou quebra, força corte no limite máximo
if ($splitPos === false || $splitPos === 0) {
$splitPos = $length;
}
// Adiciona o trecho atual ao array de mensagens
$messages[] = mb_substr($current_message, 0, $splitPos, 'UTF-8');
// Inicia o próximo trecho com o conteúdo restante
$current_message = mb_substr($current_message, $splitPos, null, 'UTF-8');
}
}
// Adiciona o restante se houver
if (!empty($current_message)) {
$messages[] = $current_message;
}
// Limpeza: remove espaços e filtra strings vazias
$messages = array_map('trim', $messages);
$filtered_messages = array_filter($messages, function ($message) {
return (bool) $message;
});
return array_values($filtered_messages);
}Como Funciona
O algoritmo segue estes passos:
Normaliza quebras de linha - Converte quebras Windows (
\r\n) e Mac antigo (\r) para estilo Unix (\n) para tratamento consistente.Percorre caractere por caractere - Usa funções multibyte seguras (
mb_strlen,mb_substr) para tratar corretamente caracteres Unicode como emojis e letras acentuadas.Detecção inteligente de limites - Quando o limite é atingido, procura para trás pelo último espaço ou quebra de linha. Quebras de linha são preferidas pois representam pontos de divisão mais naturais.
Fallback para casos extremos - Se não existir ponto de divisão adequado (ex: uma única palavra muito longa), força a divisão no limite exato.
Limpeza - Remove espaços de cada trecho e elimina strings vazias que possam resultar da divisão.
Exemplos de Uso
Uso Básico
$mensagemLonga = "Esta é uma mensagem muito longa que precisa ser dividida...";
$partes = TextUtil::splitMessageByLength($mensagemLonga, 100);
foreach ($partes as $indice => $parte) {
echo "Parte " . ($indice + 1) . ": " . $parte . "\n";
}Limites Específicos por Plataforma
class DivisorMensagens
{
const INSTAGRAM_DM = 1000;
const TWITTER = 280;
const SMS = 160;
const WHATSAPP = 4096;
const TELEGRAM = 4096;
public static function paraInstagram(string $mensagem): array
{
return TextUtil::splitMessageByLength($mensagem, self::INSTAGRAM_DM);
}
public static function paraTwitter(string $mensagem): array
{
return TextUtil::splitMessageByLength($mensagem, self::TWITTER);
}
public static function paraSMS(string $mensagem): array
{
return TextUtil::splitMessageByLength($mensagem, self::SMS);
}
}Com Respostas de IA
// Obtém resposta da IA (pode ser muito longa)
$respostaIA = $anthropicService->chat($prompt);
// Divide para envio via DM do Instagram
$partes = TextUtil::splitMessageByLength($respostaIA, 1000);
foreach ($partes as $parte) {
$instagramApi->sendDirectMessage($userId, $parte);
// Adiciona delay para manter ordem das mensagens
usleep(500000); // 500ms
}Referência de Limites por Plataforma
| Plataforma | Limite | Notas |
|---|---|---|
| Instagram DM | 1.000 | Por mensagem |
| Instagram Legenda | 2.200 | Truncada em 125 no feed |
| Twitter/X | 280 | Usuários premium têm mais |
| SMS | 160 | Maior = múltiplos segmentos |
| 4.096 | Por mensagem | |
| Telegram | 4.096 | Por mensagem |
| Facebook Post | 63.206 | Mas 40-80 caracteres é ideal |
| 3.000 | Truncado em 140 no feed |
Engajamento Ideal
Estudos mostram que mensagens mais curtas geram melhor engajamento. Posts no Twitter com menos de 100 caracteres têm 17% mais engajamento. Legendas do Instagram entre 138-150 caracteres performam melhor.
Melhorias a Considerar
Adicionando Números das Partes
public static function dividirComNumeros(string $mensagem, int $limite): array
{
$partes = self::splitMessageByLength($mensagem, $limite - 10); // Reserva espaço
$total = count($partes);
if ($total === 1) {
return $partes;
}
return array_map(function ($parte, $indice) use ($total) {
return $parte . "\n\n(" . ($indice + 1) . "/" . $total . ")";
}, $partes, array_keys($partes));
}Preservando Estrutura de Parágrafos
public static function dividirPorParagrafos(string $mensagem, int $limite): array
{
$paragrafos = explode("\n\n", $mensagem);
$partes = [];
$atual = '';
foreach ($paragrafos as $paragrafo) {
$teste = $atual ? $atual . "\n\n" . $paragrafo : $paragrafo;
if (mb_strlen($teste, 'UTF-8') <= $limite) {
$atual = $teste;
} else {
if ($atual) {
$partes[] = $atual;
}
// Se parágrafo único excede limite, usa divisão por caractere
if (mb_strlen($paragrafo, 'UTF-8') > $limite) {
$partes = array_merge($partes,
self::splitMessageByLength($paragrafo, $limite));
$atual = '';
} else {
$atual = $paragrafo;
}
}
}
if ($atual) {
$partes[] = $atual;
}
return $partes;
}Considerações sobre Emojis
Emojis podem ter 1-4 bytes mas contam como 1-2 caracteres dependendo da plataforma. Teste cuidadosamente com conteúdo rico em emojis para garantir divisão precisa.
Conclusão
Dividir mensagens longas pode parecer trivial, mas fazer corretamente—respeitando limites de palavras, tratando Unicode adequadamente e limpando os resultados—faz a diferença entre uma aplicação profissional e uma experiência frustrante para o usuário.
Os principais pontos:
- Sempre use funções de string multibyte para segurança Unicode
- Prefira pontos de divisão naturais (quebras de linha > espaços > cortes forçados)
- Limpe os resultados removendo espaços e filtrando trechos vazios
- Considere otimizações específicas por plataforma para seu caso de uso
Este utilitário se torna especialmente valioso ao integrar serviços de IA em plataformas de mensagens, onde o tamanho das respostas é imprevisível e os limites de caracteres são rigorosos.

