Boucle avec wordwrap

Fermé
YameFAZE Messages postés 201 Date d'inscription mardi 24 avril 2012 Statut Membre Dernière intervention 14 mars 2021 - 23 avril 2020 à 12:57
yg_be Messages postés 22675 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 avril 2024 - 26 avril 2020 à 18:02
Bonjour à tour,

J'ai à la base wordwrap qui me coupe une chaîne tous les X caractères. Je cherche à faire une boucle qui à chaque coupure incrémenterait automatiquement le nombre de caractères pour faire une nouvelle coupure avec un peu plus de caractères... et je n'y arrive pas. Le but final est en fait d'avoir un texte qui suit le côté droit oblique (diagonale) d'une image en float left. Et comme en CSS pour le moment ce n'est pas faisable je suis obligé de passer par un bidouillage PHP.

On pourrait imaginer une boucle qui ferait quelque chose comme :
<?php
          $texte = 'bla bla bla...';
          $nbr_caracteres = 10;
          $nbr_lignes = 1;
          do {
                    echo wordwrap($texte, $nbr_caracteres, '<br />');
                    $nbr_caracteres = $nbr_caracteres + 5;
                    $nbr_lignes++;
          } while ($nbr_lignes < 10);
?>


Sauf que ça ne fonctionne pas. Et c'est logique puisque au lieu de juste couper le texte une seule fois elle coupe le texte à chaque nouvelle incrémentation. Et si je mets le echo en-dehors de la boucle là j'ai bien le texte une seule fois mais avec le même nombre de caractères à chaque coupure.

Donc est-ce que je m'y prends mal ou alors y a-t-il une autre solution ?

Merci d'avance.

3 réponses

yg_be Messages postés 22675 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 avril 2024 1 467
23 avril 2020 à 13:40
bonjour, tu décris la technique que tu utilises, et qui ne fonctionne pas.
pourrais-tu décrire ce que tu essaies d'obtenir, via un exemple?
0
yg_be Messages postés 22675 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 avril 2024 1 467
23 avril 2020 à 13:50
si j'ai bien deviné ce que tu veux obtenir, je pense que wordwrap est une fausse piste.
moi je ferais le travail en cherchant, pour chaque ligne, la position du dernier espace avant la longueur désirée pour cette ligne, ce qui permet de déterminer le contenu de la ligne, et de retirer ce contenu du texte restant à afficher.
0
YameFAZE Messages postés 201 Date d'inscription mardi 24 avril 2012 Statut Membre Dernière intervention 14 mars 2021 > yg_be Messages postés 22675 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 avril 2024
23 avril 2020 à 15:12
D'accord, mais comment PHP peut-il déterminer le dernier espace de chaque ligne ? Sachant qu'il s'agit en fait d'un texte avec plusieurs paragraphes et qui est contraint à des limitations avec des width ? Voir image ci-dessous (le texte doit suivre la ligne rouge, donc chaque nouvelle ligne doit avoir un retrait gauche un peu plus important).

0
yg_be Messages postés 22675 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 avril 2024 1 467 > YameFAZE Messages postés 201 Date d'inscription mardi 24 avril 2012 Statut Membre Dernière intervention 14 mars 2021
23 avril 2020 à 15:18
tu connais N, la longueur maximale de la ligne. tu cherches le dernier espace dans les N premiers caractères.
https://www.php.net/manual/fr/function.strrpos.php
0
YameFAZE Messages postés 201 Date d'inscription mardi 24 avril 2012 Statut Membre Dernière intervention 14 mars 2021 > yg_be Messages postés 22675 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 avril 2024
23 avril 2020 à 17:37
Merci. J'ai bien compris l'utilité de strrpos. Ce que je veux dire c'est comment PHP peut-il connaître l'emplacement du dernier espace de chaque ligne avant même que le texte ne soit affiché ? Il ne peut pas savoir que le texte va faire X caractères à la première ligne. Sauf si je lui dis d'avance. Mais ça reviendrait à perdre en automatisme. Parce qu'il faudrait que j'affiche le texte, que je compte sur mon écran combien de caractères fait la première ligne, et que ensuite je le dise à PHP. Et donc ça m'obligerait à faire ça pour chaque taille d'écran... pas terrible pour du responsive. Je ne sais pas si tu vois ce que je veux dire.

Le but c'est :
1 - Récupérer le texte
2 - Dire à PHP coupe le texte tous les X caractères, mais à chaque fois rajoute tant de caractères à X
OU (peut-être)
2 - Dire à PHP de jouer sur le padding-left, coupe le texte tous les X caractères, mais à chaque fois retire 0.5em au padding-left
3 - Afficher le texte

En fait l'idéal serait d'afficher d'abord le texte, de dire à PHP de lire le texte, et ensuite de travailler dessus... sauf que ce n'est pas ce que je veux faire. Je veux pouvoir travailler sur le texte avant de l'afficher.
0
yg_be Messages postés 22675 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 avril 2024 1 467 > YameFAZE Messages postés 201 Date d'inscription mardi 24 avril 2012 Statut Membre Dernière intervention 14 mars 2021
23 avril 2020 à 19:03
je ne vois pas où est la difficulté de faire ceci:
1 - Récupérer le texte
2 - tant que texte n'est pas vide
- retirer les X premiers caractères du texte, et les ajouter à textefinal
- ajouter tant à X
3 - Afficher textefinal



ce serait plus clair si tu prenais un peu de temps pour présenter un exemple
0
YameFAZE Messages postés 201 Date d'inscription mardi 24 avril 2012 Statut Membre Dernière intervention 14 mars 2021
Modifié le 25 avril 2020 à 01:36
J'ai écris un bout de code qui fonctionne mais c'est vraiment du bidouillage... et je ne trouve pas ça très propre. En effet, étant donné que mon image est en float: left, le texte se colle naturellement contre l'image, mais le paragraphe lui dans le flux passe sous l'image, du coup je ne peux pas jouer sur le margin-left proprement, je suis obligé de bidouiller avec du position: relative et du margin-left négatif.

Y a-t-il un moyen pour que avec le positionnement float de l'image le paragraphe ne passe pas sous l'image ? Ou alors il va falloir que j'utilise une Flexbox.

Et autre question, mon bout de code fonctionne plutôt bien si l'on n'est pas choqué par le fait que les mots soient complètement coupés... comment faire pour que les mots ne soient pas coupés ou alors qu'ils soient coupés proprement avec un "-" ?

Ci-dessous mon code (je pense qu'il y a moyen de l'améliorer bien-sûr) :
/* On récupère le texte à couper et on l'intègre dans la chaîne $str... */
$str = 'Je m\'appelle Alexandre, j\'ai 200 ans, et j\'habite un monde fantastique appellé Never Land. Je suis super heureux de vous rencontrer. J\'adore faire des balades à moto dans les Alpes et en Provence.';
/* ...et on détermine le nombre de caractères de la première ligne. */
$nbr_max_caract_ligne_1 = 35;
       /* Si le nombre total de caractères de la chaîne dépasse $nbr_max_caract_ligne1,... */
 if (strlen($str) > $nbr_max_caract_ligne_1) {
  /* ...on initialise le tableau $ligne,... */
  $ligne = array();
  /* ...on définit la valeur de la première entrée de $ligne,... */
  $i_ligne = 1;
  /* ...on définit le départ de la première coupure,... */
  $start = 0;
  /* ...on définit le nombre de caractères de la première coupure,... */
  $nbr_max_caract_ligne = 35;
  /* ...on définit un nombre maximum de coupures,... */
  $nbr_max_lignes = 10;
  /* ...on définit une valeur de départ pour la position des paragraphes,... */
  $position = 0;
  /* ...on définit une valeur de départ pour la largeur des paragraphes,... */
  $largeur = 98;
  /* ...puis on lance une boucle. */
  do {
   /* On coupe la chaîne à partir de $start jusqu'à $nbr_max_caract_ligne et on intègre la partie récupérée comme première entrée dans $ligne,... */
   $ligne[$i_ligne] = substr($str, $start, $nbr_max_caract_ligne);
   /* ...on affiche l'entrée,... */
   echo '<p style="left: '.$position.'%; width: '.$largeur.'%;">'.$ligne[$i_ligne].'</p>';
   /* ...on incrémente $i_ligne de 1,... */
   $i_ligne++;
   /* ...on incrémente $start,... */
   $start = $start + $nbr_max_caract_ligne;
   /* ...on incrémente $nbr_max_caract_ligne,... */
   $nbr_max_caract_ligne = $nbr_max_caract_ligne + 1;
   /* ...on décrémente $position,... */
   $position = $position - 0.3;
   /* ...puis on incrémente $largeur avant de relancer la boucle. */
   $largeur = $largeur + 0.3;
  /* La boucle doit tourner tant que $i_ligne est inférieur à $nbr_max_lignes. */
  } while ($i_ligne <= $nbr_max_lignes);
 /* Sinon..., */
 } else {}


Et voici ce que ça donne dans le navigateur (j'ai mis un background orange pour voir comment se comporte les paragraphes) :
0
yg_be Messages postés 22675 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 avril 2024 1 467
25 avril 2020 à 15:01
comment faire pour que les mots ne soient pas coupés:
chercher la position du dernier espace de
substr($str, $start, $nbr_max_caract_ligne+1)
. cela permet de déterminer où couper la ligne.
0
YameFAZE Messages postés 201 Date d'inscription mardi 24 avril 2012 Statut Membre Dernière intervention 14 mars 2021 > yg_be Messages postés 22675 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 avril 2024
25 avril 2020 à 15:23
Oui merci du coup en fait j'avais trouvé. (voir ci-dessous) ^^
0
YameFAZE Messages postés 201 Date d'inscription mardi 24 avril 2012 Statut Membre Dernière intervention 14 mars 2021
25 avril 2020 à 15:05
Bon voilà, ça prend forme petit à petit. Au final j'utilise des span pour chaque ligne le tout englobé dans un seul paragraphe. C'est plus propre. J'ai réussi à faire en sorte que les mots ne soient pas coupés. Les premières lettres du mot coupé sont supprimées de la ligne et ajoutées au début de la ligne suivante. Il faut encore que j'améliore le code car pour le moment la longueur des lignes ne prend pas en compte ces suppressions et ajouts, du coup je me retrouve avec un problème de longueur de caractères sur certaines lignes.

/* On récupère le texte à couper et on l'intègre dans la chaîne $str. */
$str = 'Je m\'appelle Alexandre, j\'ai 200 ans, et j\'habite un monde fantastique appellé Never Land. Je suis super heureux de vous rencontrer. J\'adore faire des balades à moto dans les Alpes et en Provence.';
/* On détermine le nombre maximum de caractères de la première ligne d'affichage. */
$nbr_max_caract_ligne_1 = 35;
/* On débute l'affichage du texte. */
echo '<p>';
/* Si le nombre total de caractères de la chaîne dépasse $nbr_max_caract_ligne1 on suit les instructions spécifiques. */
if (strlen($str) > $nbr_max_caract_ligne_1) {
	/* On initialise le tableau $sub_str. */
	$sub_str = array();
        /* On définit la valeur de la première entrée de $sub_str. */
	$i_sub_str = 1;
	/* On définit le départ de la première coupure. */
	$start = 0;
	/* On définit le nombre de caractères de la première coupure. */
	$nbr_max_caract_ligne = 35;
	/* On définit un nombre maximum de coupures. */
	$nbr_max_lignes = 10;
	/* On définit une valeur de départ pour la marge gauche des span. */
	$marge_gauche = 0;
	/* On initialise une boucle. */
	do {
		/* On coupe la chaîne à partir de $start jusqu'à $nbr_max_caract_ligne et on enregistre la sous-chaîne dans $sub_str. */
		$sub_str[$i_sub_str] = substr($str, $start, $nbr_max_caract_ligne);
		/* On recherche la position du dernier espace dans $sub_str[$i_sub_str] et on l'enregistre dans $pos_esp. */
		$pos_esp = strrpos($sub_str[$i_sub_str], ' ');
		/* On récupère le début de la sous-chaîne jusqu'à la position du dernier espace et on l'enregistre dans $start_sub_str. */
       	$start_sub_str = substr($sub_str[$i_sub_str], 0, $pos_esp);
		/* On débute l'affichage de la sous-chaîne. */
		echo '<span style="margin-left: '.$marge_gauche.'%;">';
		/* S'il ne s'agit pas du premier passage de la boucle on suit les instructions spécifiques. */
		if ($i_sub_str > 1) {
			/* On affiche la fin de la sous-chaîne précédente au début de la sous-chaîne suivante. */
			echo '<span style="color: red;">'.$end_sub_str.'</span>';
		}
		/* On termine l'affichage de la sous-chaîne. */
		echo $start_sub_str.'</span><br />';
		/* On récupère la fin de la sous-chaîne à partir de la position du dernier espace et on l'enregistre dans $end_sub_str. */
		$end_sub_str = substr($sub_str[$i_sub_str], $pos_esp);
		/* On incrémente $i_sub_str de 1. */
		$i_sub_str++;
		/* On incrémente $start. */
		$start = $start + $nbr_max_caract_ligne;
		/* On incrémente $nbr_max_caract_ligne. */
		$nbr_max_caract_ligne = $nbr_max_caract_ligne + 1;
		/* On décrémente $marge_gauche. */
		$marge_gauche = $marge_gauche - 0.3;
		/* La boucle doit tourner tant que $i_sub_str est inférieur à $nbr_max_lignes. */
	} while ($i_sub_str <= $nbr_max_lignes);
	/* Sinon on suit les autres instructions. */
} else {
	/* On affiche le texte sans coupure. */
	echo $str;
}
echo '</p>';


0
yg_be Messages postés 22675 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 avril 2024 1 467
25 avril 2020 à 15:26
je me demande juste si il est utile d'utiliser une array pour $sub_str[], il me semble que tu n'utilises jamais les valeurs précédentes.
0
YameFAZE Messages postés 201 Date d'inscription mardi 24 avril 2012 Statut Membre Dernière intervention 14 mars 2021 > yg_be Messages postés 22675 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 avril 2024
25 avril 2020 à 18:06
L'utilisation d'un array me paraît la solution la plus simple. Mais si tu as une autre idée je suis preneur bien-sûr.
0
yg_be Messages postés 22675 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 avril 2024 1 467 > YameFAZE Messages postés 201 Date d'inscription mardi 24 avril 2012 Statut Membre Dernière intervention 14 mars 2021
25 avril 2020 à 20:58
j'ai peut-être mal lu ton code. j'ai eu l'impression que tu n'avais pas besoin de mémoriser les multiples valeurs de l'array, et que tu pouvais remplacer l'array par une variable. et donc remplacer
$sub_str[$i_sub_str]
par
$sub_str
.
cela me semble plus clair comme code.
0
YameFAZE Messages postés 201 Date d'inscription mardi 24 avril 2012 Statut Membre Dernière intervention 14 mars 2021 > yg_be Messages postés 22675 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 avril 2024
26 avril 2020 à 17:44
Bah en fait... tu avais raison. Pas besoin d'un array. ^^

J'ai vachement simplifié le code :
<?php
	/* On récupère la chaîne à couper et on l'intègre dans $str. */
	$str = 'Je m\'appelle Alexandre, j\'ai 200 ans, et j\'habite un monde fantastique appellé Never Land. Je suis super heureux de vous rencontrer. J\'adore faire des balades à moto dans les Alpes et en Provence. Je m\'appelle Alexandre, j\'ai 200 ans, et j\'habite un monde fantastique appellé Never Land. Je suis super heureux de vous rencontrer. J\'adore faire des balades à moto dans les Alpes et en Provence. Je m\'appelle Alexandre, j\'ai 200 ans, et j\'habite un monde fantastique appellé Never Land. Je suis super heureux de vous rencontrer. J\'adore faire des balades à moto dans les Alpes et en Provence. Je m\'appelle Alexandre, j\'ai 200 ans, et j\'habite un monde fantastique appellé Never Land. Je suis super heureux de vous rencontrer. J\'adore faire des balades à moto dans les Alpes et en Provence. Je m\'appelle Alexandre, j\'ai 200 ans, et j\'habite un monde fantastique appellé Never Land. Je suis super heureux de vous rencontrer. J\'adore faire des balades à moto dans les Alpes et en Provence. FIN';
	/* On définit le nombre de caractères de la première sous-chaîne et on l'enregistre dans $nbr_char_substr. */
	$nbr_char_substr = 40;
	/* On débute l'affichage du paragraphe. */
	echo '<p>';
	/* Si le nombre total de caractères de la chaîne dépasse $nbr_char_substr on suit les instructions ci-dessous. */
	if (strlen($str) > $nbr_char_substr) {
		/* On définit un index et on l'enregistre dans $i. */
		$i = 1;
		/* On définit le point de départ de la première sous-chaîne et on l'enregistre dans $start. */
		$start = 0;
		/* On définit le nombre maximum de sous-chaînes et on l'enregistre dans $nbr_substr. */
		$nbr_substr = 19;
		/* On définit une valeur pour la marge gauche de la première sous-chaîne et on l'enregistre dans $marginleft. */
		$marginleft = 0;
		/* On initialise une boucle. */
		do {
			/* On coupe la chaîne à partir de $start jusqu'à $nbr_char_substr et on enregistre la sous-chaîne dans $substr. */
			$substr = substr($str, $start, $nbr_char_substr);
			/* On recherche la position du dernier espace dans $substr et on l'enregistre dans $pos_esp. */
			$pos_esp = strrpos($substr, ' ');
			/* On récupère le début de la sous-chaîne jusqu'à la position du dernier espace et on l'enregistre dans $start_substr. */
			$start_substr = substr($substr, 0, $pos_esp);
			/* On supprime les éventuels espaces en début de sous-chaîne. */
			$start_substr = ltrim($start_substr);
			/* On récupère la fin de la sous-chaîne à partir de la position du dernier espace et on l'enregistre dans $end_substr. */
			$end_substr = substr($substr, $pos_esp);
			/* On définit le nombre de caractères dans $end_substr et on l'enregistre dans $nbr_char_end_substr. */
			$nbr_char_end_substr = strlen($end_substr);
			/* S'il s'agit du dernier passage de la boucle on suit les instructions ci-dessous. */
			if ($i == $nbr_substr) {
				/* On affiche la dernière sous-chaîne en ajoutant $end_last_substr à sa fin et en retirant le retour à la ligne. */
				echo '<span style="margin-left: '.$marginleft.'%;">'.$start_substr.$end_last_substr.'</span>';
			/* Sinon on suit les instructions ci-dessous. */
			} else {
				/* On affiche normalement la sous-chaîne. */
				echo '<span style="margin-left: '.$marginleft.'%;">'.$start_substr.'</span><br />';
			}
			/* On incrémente $i de 1. */
			$i++;
			/* On ajuste $start. */
			$start = $start + $nbr_char_substr - $nbr_char_end_substr;
			/* S'il s'agit de l'avant-dernier passage de la boucle on suit les instructions ci-dessous. */
			if ($i == ($nbr_substr - 1)) {
				/* On définit la fin de la dernière sous-chaîne et on l'enregistre dans $end_last_substr. */
				$end_last_substr = '[...]';
				/* On définit le nombre de caractères dans $end_last_substr et on l'enregistre dans $nbr_char_end_last_substr. */
				$nbr_char_end_last_substr = strlen($end_last_substr);
				/* On incrémente $nbr_char_substr en prenant en compte le nombre de caractères dans $nbr_char_end_last_substr. */
				$nbr_char_substr = $nbr_char_substr + 0.40 - $nbr_char_end_last_substr;
			/* Sinon on suit les instructions ci-dessous. */
			} else {
				/* On incrémente normalement $nbr_char_substr. */
				$nbr_char_substr = $nbr_char_substr + 0.40;
			}
			/* On décrémente $marginleft. */
			$marginleft = $marginleft - 0.28;
		/* La boucle doit tourner tant que $i_substr est inférieur à $nbr_substr. */
		} while ($i <= $nbr_substr);
	/* Sinon on suit les instructions ci-dessous. */
	} else {
		/* On affiche la chaîne entière sans coupure. */
		echo $str;
	}
	/* On termine l'affichage du paragraphe. */
	echo '</p>';
?>


Et voilà le résultat :


Que de code pour juste faire du bidouillage esthétique... mais bon, heureusement que PHP est là sinon on resterait limité avec CSS. Vivement qu'ils intègrent ce genre de possibilité dans les futurs versions de CSS.

J'ai encore 2 questions :
- Sais-tu comment récupérer un texte sur une autre page ? En fait le texte que je souhaite afficher serait la reprise du texte d'une actualité sur une autre page de mon site. Il faudrait donc que je puisse le récupérer automatiquement. Comme ça lorsque je publie une nouvelle actualité le texte serait automatiquement mis à jour sur l'index que tu peux voir sur l'image.
- Et sais-tu s'il y aurait moyen de justifier le texte affiché ? Parce que la méthode de l'ajout de span au début de chaque ligne est bien pour ensuite contrôler l'alignement gauche mais du coup je perds l'effet justifié du texte à droite. En fait c'est comme si le texte était juste aligné à gauche... Et les span sont les seules balises à ma connaissance pour marquer le début de chaque ligne.
0
yg_be Messages postés 22675 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 13 avril 2024 1 467 > YameFAZE Messages postés 201 Date d'inscription mardi 24 avril 2012 Statut Membre Dernière intervention 14 mars 2021
26 avril 2020 à 18:02
justifier? aucune idée! à tout hasard: https://developer.mozilla.org/fr/docs/Web/CSS/text-justify
partager un texte entre deux pages? il me semble que cela implique de sauver quelque part ce texte sur ton site. par exemple dans un fichier ou une base de données.
comment le texte arrive-t'il sur le site?
0