[PHP]Fonction substr()

Nouveau WRInaute
Bonjour,
Je réalise actuellement des sites dont l'affichage des news est "tronqué" grace à la fonction substr() ... et jusque là tout est bon.
Seulement pour la validité de mon code il y a un problème majeur: en effet la fonction substr() me prend un nombre x de caractère mais ne prend pas exclusivement le texte, il coupe les balises 8O .
Par exemple j'avais une liste avec <ul><li>exemple</li></ul> et la fonction ma coupé le texte à <u et le code devient donc invalide.

J'ai réfléchis mais je ne vois pas trop comment, enfin si mais avec des calculs et des conditions de partout :s

Merci d'avance.
 
WRInaute impliqué
J'ai trouvé cette fonction, à toi de voir si elle te convient bien:

Code:
<?php
// pour l'utiliser, tu fait 
// $mavariable = shorten($mavariable, longueur-en-chiffres);
// il y a un exemple en bas, après la fonction
function shorten($source, $toLen)
{
$p = 0;
$pEnd = - 1;
$len = strlen($source);
$tags = array();

if($len <= $toLen) // the string is already short enough
{
return $source;
}

do
{
$p = strpos($source, '<', $pEnd + 1);
if(FALSE === $p) // no more tags in the string
{
$p = $pEnd + 1 + $toLen;
break;
}

$toLen -= $p - $pEnd - 1;
if($toLen < 0) // already enough chars gathered
{
$p += $toLen;
break;
}

$pEnd = strpos($source, '>', $p + 1);
if(FALSE === $pEnd) // no closing angle for the tag found -> stop before the tag
{
break;
}

$tag = explode(' ', trim(substr($source, $p + 1, $pEnd - $p - 1)));

if('/' != $tag[count($tag) - 1] && $tag[0][strlen($tag[0]) - 1] != '/') // tag should have a closing tag
{
if('/' == $source[$p + 1]) // closing tag
{
$i = $j = count($tags);
while(--$i >= 0)
{
if($tags[$i] == $tag[0]) // tag is in the list of open tags
{
if($i != $j - 1) // if some tags are not properly closed -> insert closing tags into source
{
$ins = '<'.implode('><', array_reverse(array_slice($tags, $i + 1))).'>';
$source = substr($source, 0, $p).$ins.substr($source, $p);
$p = strlen($ins);
$len += $p;
$pEnd += $p;
}

array_splice($tags, $i); // remove tag from the list
break;
}

}
if($i == -1) // no matching opening tag found -> remove closing tag from source
{
$source = substr($source, 0, $p).substr($source, $pEnd + 1);
$len = strlen($source);
$pEnd = $p - 1;
}
}
else // opening tag
{
$tags[] = '/'.$tag[0];
}
}
}
while(TRUE);

$str = substr($source, 0, $p);
$i = count($tags);
while(--$i >= 0) // append a closing tag for each unclosed open tag
{
$str .= '<'.$tags[$i].'>';
}

return $str;
}

// comment l'utiliser:
$str = 'hello <b>world!</b> <i>Ca va bien</i>? <br/><b><u><i>Ca va nickel.</i></u></b>';

echo shorten($str, 29);
?>

A ce qu'il parait cette fonction ne marche que si toutes les balises qui n'ont pas de balises de fermeture ont un / avant le signe plus grand que... ex:
Code:
<br> pas bon
<br /> bon
 
WRInaute impliqué
strip_tags ne résoud pas le problème car ensuite on se retrouve avec un texte sans balises.
Par contre si les balises sont un peu complexes il vaut mieux dans ce cas virer toutes les balises en effet.
 
WRInaute accro
Si c'est pour afficher un snippet, pas besoin de mise en forme.
En tout cas, ce sera toujours mieux que de se retrouver avec des balises non fermées. Par exemple un strong en début de texte et pas fermé à cause du tronquage, mettra tout le reste du site en gras... Pas terrible...
 
Nouveau WRInaute
Tout d'abord merci de vos réponse.

VisitezMonSite peut tu m'en dire un peu plus sur la fonction ? Sinon je ferait des test mais elle est pas claire je trouve ^^.
 
WRInaute impliqué
C'est vrai, c'est le plus sûr pour ne pas avoir de problème et bien contrôler l'extrait/snippet.

@Akuma, en gros la fonction va regarder si il y a des balises non fermées, et va rajouter une balise de fermeture a la fin de l'extrait pour toutes les balises non fermées (sauf celles qui sont unique, d'ou l'importance d'avoir un / comme dans < br/ > et non < br >)

Fais des tests, cela devrait bien marcher, cela fermera meme si il y a un < strong > des le debut de ta chaine de caracteres.
Mais comme ca a été dit, perso je prefère virer tout le html pour afficher un extrait, mais c'est vrai que je n'avais jamais cherché et donc trouvé cette fonction auparavant, si elle fonctionne bien et que tu controles ton contenu (pas de contenu envoyé par les utilisateurs) alors ca devrait meme etre mieux visuellement.
 
Discussions similaires
Haut