Abreviando um texto sem cortar palavras no PHP
Olá Pessoal!
Como apresentar soluções para problemas cotidianos, é um dos objetivos deste blog, vou compartilhar com vocês uma solução que escrevi para que vocês possam abreviar um texto, sem cortar qualquer palavra pela metade.
É extremamente chato, quando estamos lendo o resumo de uma notícia e nos deparamos com uma palavra cortada, dificultando a compreensão do texto. É feio, principalmente para a estética do layout.
A maioria das funções escritas (em qualquer linguagem) para abreviar um texto, acabam cortando o texto pela metade. Você passa 2 parâmetros: String Texto e Int Limite.
Texto é o texto própriamente dito, e Limite é o tamanho máximo que o texto deve ocupar. Se o texto for maior que 250 caractéres, o script abrevia o texto sem estourar o limite e sem cortar palavras pela metade, caso contrário, deixa o textocomo está.
A solução que escrevi foi esta:
public function abreviaString($texto, $limite, $tres_p = '...') { $totalCaracteres = 0; //Retorna o texto em plain/text $texto = Biblioteca::somenteTexto($texto); //Cria um array com todas as palavras do texto $vetorPalavras = explode(" ",$texto); if(strlen($texto) <= $limite): $tres_p = ""; $novoTexto = $texto; else: //Começa a criar o novo texto resumido. $novoTexto = ""; //Acrescenta palavra por palavra na string enquanto ela //não exceder o tamanho máximo do resumo for($i = 0; $i <count($vetorPalavras); $i++): $totalCaracteres += strlen(" ".$vetorPalavras[$i]); if($totalCaracteres <= $limite) $novoTexto .= ' ' . $vetorPalavras[$i]; else break; endfor; endif; return $novoTexto . $tres_p; }
Note que eu chamei uma função estática chamada somenteTexto(). Quem quiser o fonte dela e saber como ela está implementada, está ai:
public static function somenteTexto($string) { $trans_tbl = get_html_translation_table(HTML_ENTITIES); $trans_tbl = array_flip($trans_tbl); return trim(strip_tags(strtr($string, $trans_tbl))); }
Esta é a solução enviada pelo Carlos André Ferrari nos comentários do blog:
function abreviaString($texto, $limite, $tres_p = '…') { //Retorna o texto em plain/text $texto = Biblioteca::somenteTexto($texto); if (strlen($texto) <= $limite) return $texto; return array_shift(explode('||', wordwrap($texto, $limite, '||'))) . $tres_p; }
É importante que, antes de abreviarmos um texto, recebermos o texto puro, livre de tags htmls, scripts ou qualquer outra coisa que não faça parte do texto. Quando isso ocorre, dificulta a abreviação pois o algoritmo não sabe o que é texto e o que é metacaracter.
E é isso aí pessoal, o código está bem comentádo e documentado, caso vocês tenham alguma dúvida, fiquem a vontade para perguntar nos comentários.
Qualquer outra implementação que vocês tenham, que faça a mesma coisa, até mesmo em outras linguagens, o share é totalmente bem-vindo.
[]’s
Igor.
Olá, Igor.
Realmente palavras pela metade ficam bem deselegantes. Porém, creio que a função “wordwrap” do próprio PHP já ajude com isso. O único complemento seria incluir os três pontos, caso ocorreu redução do texto.
Outra solução alternativa que vi recentemente é baseada em CSS 3. Escrevi sobre isso lá no meu blog. A visita é bem vinda:
http://rubsphp.blogspot.com/2011/08/text-overflow.html
A vantagem dela é que o texto é quebrado de acordo com a largura do navegador (e do espaço reservado ao texto), e a quebra fica por conta do próprio navegador realizar.
Olá Rubéns!
O método wordwrap não serve para “abreviar” um texto e sim para forçar a quebra de linha ou algo do gênero.
Utilização boa do wordwrap é quando não queremos que uma palavra muito grande anule o “truncate” automático do browser.
$text = "A very long woooooooooooord.";
$newtext = wordwrap($text, 8, "\n", true);
echo "$newtext\n";
A very
long
wooooooo
ooooord.
A função que eu passo acima ela faz outra coisa.
Ela limpa os metacaracteres da string, corta a atring e quando corta ela não deixa palavras pela metade, entendeu?
sempre usei a wordwrap:
function abreviaString($texto, $limite, $tres_p = ‘…’) {
if (strlen($texto) <= $limite) return $texto;
return array_shift(explode('||', wordwrap($texto, $limite, '||'))) . $tres_p;
}
echo abreviaString('O rato roeu a roupa do rei de roma', 50);
Parabéns pelos artigos, mas eu cortaria a frase a um limite considerável (depende do layout em questão) e usaria o bom e velho CSS para resolver o problema, assim como o google faz no gMail/gDocs 😀
Puts, é verdade (viajei aqui). Em todo caso, fica a sugestão do text-overflow.
Muito legal cara, vou estudar mais sobre isso. Estou montando um portal no WordPress e um dos problemas que venho enfrentando é sobre isso, definir um número de caracteres não resolveu 100%.
Agora vou ver como consigo aplicar isso no WordPress, tem alguma dica?
Obrigado pelo post de qualquer forma!
Eu também faço desta forma, Mike 🙂
Vale lembrar que nem todas as aplicações PHP são web, então, todo snippet é válido 🙂
Fala Carlos!
Você está usando o wordwrap para truncar palavras, e este é o propósito da função. A sua solução também é válida, posso agrega-la ao post?
Bem mais inteligente by the way ;D
O problema é se no texto abreviado tiver || também, né? (hehehe)
claro que pode agregar kra.. nem precisava perguntar.
Eu não sabia como utilizar wordwrap para este fim e sempre fiz de forma semelhante ao que o Igor escreveu, valeu Carlos! Valeu também Igor!
Bruno, o the_excerpt(); do WordPress já faz o efeito previsto neste post, retorna um limite sem cortar palavras.
Sempre vejo os posts do Igor Escobar, ajuda muito quem está iniciando PHP, e esta função aí é super interessante. Valeu Carlos & Igor.
Estou com uma dúvida, estou usando o while do SQL e ele me retorna um erro desse tipo: ” Fatal error: Cannot redeclare abreviaString() (previously declared in..”
vc ta repetindo a função em algum lugar
poxa
que função que me ajudou muito
valeu meu queridão
Att,
Cornélio José Wiedemann ( TI & DBA )