8722 sujets

Développement web côté serveur, CMS

Voila je dois générer des pdfs et faire des jolies phrases à l’intérieur. Le problème c'est que faire des jolies phrases impliquent à ma connaissance une multitude de "if/elseif/else". Cette sur-utilisation des if rends le code illisible et moche. Avez-vous déjà rencontré cette situation comment avez-vous fait ?
Bonjour,

Si je comprends bien votre question, vous voulez générer une phrase aléatoire basée sur un fichier (ou une base) de données ?

Vous pouvez en PHP (et dans toute autre langage mais je ne sais pas lequel vous utilisez ici) utiliser la fonction rand() qui génèrera un nombre aléatoire compris entre deux chiffres, et ainsi aller chercher dans un tableau de données la phrase associée au nombre...

Un exemple simple :
<?php
$phrases = array("phrase 1","phrase 2","etc..."); // tu peux bien sur alimenter ce tableau à partir d'une base de données ou autre.
for($i=0; $i < 19; $i++)
{
   $rand = rand(0,19); // dans le cas de 20 phrases
   echo $phrases[$rand];
} 
?>

Si vous ne générez pas ces phrases de manière aléatoire, alors il vous suffit d'utiliser un switch, qui est adapté pour remplacer une structure if else else importante.

Je te renvoie vers la documentation :
http://www.php.net/manual/fr/control-structures.switch.php
Modifié par ohweb (03 Jun 2014 - 12:25)
Mince non, je me rends compte que je me suis mal exprimé.
J'ai énormément de valeur qui peuvent être vides ou remplis.
Exemple : ville de naissance, age, nom, prenom.
Et je dois écrire quelque-chose comme ça :

L'utilisateur jean dupont est agé de 28 ans et habite à superville


Mais si la date de naissance n'est pas renseignée

L'utilisateur jean dupont habite à superville


etc...
Je cherche un moyen d’éviter l’écriture longue et fastidieuse des multiples if qui présuppose la bonne écriture de cette phrase peut importe si les données sont vides ou remplis.

Je pense que c'est un problème récurent, et par conséquent vous avez peut-être la solution à mon problème.
Modifié par Su4p (03 Jun 2014 - 15:02)
D'accord, peut-être quelque chose comme ceci ?

<?php
foreach($infos as $info => $valeur)
{
	// L'utilisateur jean dupont est agé de 28 ans et habite à superville
	echo "L'utilisateur ";
	if($valeur != "")
	{
		switch($info)
		{
			case "nom": echo $valeur." "; break;
			case "age": echo "est âgé de ".$valeur." ans "; break;
			case "lieu": echo "et habite à ".$valeur; break;
		}
	}
}
?>
J'ai eu à faire la même chose et voilà comment j'ai procédé :


$user_details = [
	'name' => 'John Doe',
	'age' => '28',
	'city' => 'New-York',
];

/*
 * les clés du tableau sont les hashs md5 des différentes combinaisons possibles.
 * ex : md5('nameagecity') = db3dfff82113f52bcaf63170af75af00
 */
$templates = [
	'db3dfff82113f52bcaf63170af75af00' => 'L’utilisateur %s a %s ans et habite à %s.',
	'28206ac38306114c1d8c234b17b4c3a7' => 'L’utilisateur %s a %s ans.',
	'f05d30e380a8e43ddda4ba53d976a895' => 'L’utilisateur %s habite à %s.',
];

$keys = '';

foreach ($user_details as $k => $v) {
	if (!empty($v)) {
		$keys .= $k;
	}
}

$hash = md5($keys);

$output = vsprintf($templates[$hash], $user_details);

echo $output;

Modifié par FraiseTagada99 (03 Jun 2014 - 19:21)
Bonjour,

La solution de FraiseTagada99 est astucieuse et devrait fonctionner, bien qu'un peu lourd à mon goût pour ce genre de traitement Smiley smile

Un simple if après le switch fait l'affaire dans ce cas de figure :
<?php
$infos = array();
$infos["nom"] = "jean moulin";
$infos["age"] = "25";
$infos["lieu"] = "Lyon";

echo "L'utilisateur ";
foreach($infos as $info => $valeur)
{
	// L'utilisateur jean dupont est agé de 28 ans et habite à superville
	if($valeur != "")
	{
		switch($info)
		{
			case "nom": echo $valeur." "; break;
			case "age": echo "est âgé de ".$valeur." ans "; break;
			case "lieu": echo "habite à ".$valeur; break;
		}
		if($info == "age"){ echo "et "; }
	}
}
?>

Bien sur, si tes phrases deviennent assez complexes et nécessite de penser à beaucoup de combinaisons possibles, l'astuce de FraiseTagada sera plus confortable à long terme.
Modifié par ohweb (04 Jun 2014 - 10:02)
Qu'est ce que tu entends par "lourd" ?

L'avantage avec la méthode que je propose est de garder une bonne séparation entre le code et le contenu textuel que tu peux facilement stocker dans des fichiers externes ou une base de données. C'est beaucoup plus souple que d'aller imbriquer des bout de phrases dans des conditions PHP. Et puis peu importe l'évolution le code ne se complexifie jamais dans le temps.
Moi j'aurais fait ça ainsi :

$info=array("nom"=>"Jean","age"=>"28","ville"=>"Bruxelles","sexe"=>"H");
/*autre exemple : $info=array("nom"=>"Aurélie","age"=>"19","ville"=>"Wavre","sexe"=>"F");*/

/*Les deux templates doivent être complété, la clé correspond aux champs complétés des utilisateurs*/
$template['M']=array('NomAgeVille' => 'L’utilisateur %nom a %age ans et habite à %ville.',
	'NomAge' => 'L’utilisateur %nom a %age ans.',
	'NomVille' => 'L’utilisateur %nom habite à %ville.');

$template['F']=array('NomAgeVille' => 'L’utilisatrice %nom a %age ans et habite à %ville.',
	'NomAge' => 'L’utilisatrice %nom a %age ans.',
	'NomVille' => 'L’utilisatrice %nom habite à %ville.');

/*a complété si d'autres champs sont ajoutés. La clé correspond au nom du champs, la valeur au code du template*/
$remplacement=array("nom"=>"%nom","age"=>"%age","ville"=>"%ville"); 

$sexe="M";
$cleTemplate="";
foreach($info as $k=>$v)
{
     if($k=="sexe"){$sexe=$v;}
     elseif(!empty($v)){$cleTemplate.=$k;}
}

$phrase=$template[$sexe][$cleTemplate];

foreach($remplacement as $champs => $string)
{
     $phrase=str_replace($string, $info[$champs], $phrase);
}


Plus simple à maintenir et plus clair qu'avec un hash, permet l'ajout de nouveaux champs autant que de nouvelles phrases, couvre le cas où les champs sont vides (résultats de bases de données), permet une séparation entre la partie textuelles et les données; peut être maintenu sans toucher au code qui génère la phrase; permet de couvrir un template différent en fonction d'une variable (tel le sexe de l'utilisateur... ou un passage en multilingue).
En gros tu aurais copié/collé mon code, changé le nom des variables et supprimé le hash. Smiley smile

Si je passe pas un hash c'est pas juste pour faire joli. Comment tu fais avec des textes complexes contenant des dizaines de variables ?

$templates = ['NomAgeVilleDepartementRegionPaysTaillePoidsCouleurDesCheveuxCouleurDesYeuxProfessionFormation' =>
...

Je te rejoins par contre pour les variables nommées dans les templates puisque c'est ce que j'ai fait sur mon projet. Je donnais juste un code d'exemple.
Modifié par FraiseTagada99 (04 Jun 2014 - 13:27)
FraiseTagada99 a écrit :
Qu'est ce que tu entends par &quot;lourd&quot; ?
L'avantage avec la méthode que je propose est de garder une bonne séparation entre le code et le contenu textuel que tu peux facilement stocker dans des fichiers externes ou une base de données. C'est beaucoup plus souple que d'aller imbriquer des bout de phrases dans des conditions PHP. Et puis peu importe l'évolution le code ne se complexifie jamais dans le temps.


Je suis d'accord avec toi, d'où ma précision ci-dessus :
a écrit :
Bien sur, si tes phrases deviennent assez complexes et nécessite de penser à beaucoup de combinaisons possibles, l'astuce de FraiseTagada sera plus confortable à long terme.

Pour ce qui est de la proposition de Lothindil, je ne vois vraiment pas en quoi cela simplifie la chose, beaucoup plus de code et plus fastidieux à maintenir, sans parler des str_replace...

La solution de FraiseTagada99 me semble plus appropriée en cas de phrases complexes...
Modifié par ohweb (04 Jun 2014 - 13:32)
L'avantage de mon code ?

Son gros point positifi est de permettre un dédoublement du template, voire une multiplication (gestion sexe + langue par exemple) en fonction d'un (ou de plusieurs) champs de user tout en étant plus clair. J'avoue trouver ça plus clair :

$template['M']['fr']=array('NomAgeVille' => 'L’utilisateur %nom a %age ans et habite à %ville.',
	'NomAge' => 'L’utilisateur %nom a %age ans.',
	'NomVille' => 'L’utilisateur %nom habite à %ville.');

$template['M']['en']=array('NomAgeVille' => 'The user %nom is %age and lives in %ville.',
	'NomAge' => 'The user %nom is %age.',
	'NomVille' => 'The user %nom lives in %ville.');

$template['F']['fr']=array('NomAgeVille' => 'L’utilisatrice %nom a %age ans et habite à %ville.',
	'NomAge' => 'L’utilisatrice %nom a %age ans.',
	'NomVille' => 'L’utilisatrice %nom habite à %ville.');

$template['F']['en']=array('NomAgeVille' => 'The user %nom is %age and lives in %ville.',
	'NomAge' => 'The user %nom is %age.',
	'NomVille' => 'The user %nom lives in %ville.');


que
$template=array(
	'MFrNomAgeVille' => 'L’utilisateur %nom a %age ans et habite à %ville.',
	'MFrNomAge' => 'L’utilisateur %nom a %age ans.',
	'MFrNomVille' => 'L’utilisateur %nom habite à %ville.'
	'MEnNomAgeVille' => 'The user %nom is %age and lives in %ville.',
	'MEnNomAge' => 'The user %nom is %age.',
	'MEnNomVille' => 'The user %nom lives in %ville.',
	'FFrNomAgeVille' => 'L’utilisatrice %nom a %age ans et habite à %ville.',
	'FFrNomAge' => 'L’utilisatrice %nom a %age ans.',
	'FFrNomVille' => 'L’utilisatrice %nom habite à %ville.',
	'FEnNomAgeVille' => 'The user %nom is %age and lives in %ville.',
	'FEnNomAge' => 'The user %nom is %age.',
	'FEnNomVille' => 'The user %nom lives in %ville.');


ou que
$template=array(
	'b1ac37e6562831893791e4a152c3fe82' => 'L’utilisateur %nom a %age ans et habite à %ville.',
	'e051f95685303ddf28e57ed495a722ee' => 'L’utilisateur %nom a %age ans.',
	'ad3e14c38f04b392d2278dcf391e8e13' => 'L’utilisateur %nom habite à %ville.'
	'4f941c07cbc0c193bec66d37fc08e91e' => 'The user %nom is %age and lives in %ville.',
	'4544df1d5add3b2ab80ac0ef25a4a418' => 'The user %nom is %age.',
	'c6951ce698149de9cd4be67de0788d35' => 'The user %nom lives in %ville.',
	'97dc00845f6cec289a4cc10de8b92115' => 'L’utilisatrice %nom a %age ans et habite à %ville.',
	'8259a412fe4e173cee0e7b6ef40822b5' => 'L’utilisatrice %nom a %age ans.',
	'6531ddfaa241be5a7db7277db096d50d' => 'L’utilisatrice %nom habite à %ville.',
	'eddd351e7974f97171580e3b81b90d99' => 'The user %nom is %age and lives in %ville.',
	'61cca214dc9db56724e7c676f87c9f8f' => 'The user %nom is %age.',
	'209062ae56f4b8e02a7d922fa27e99bb' => 'The user %nom lives in %ville.');


que ça soit à maintenir, à mettre à jour ou à compléter. Smiley langue

Après, avec des dizaines de variables, j'aurais plutôt tendance à entrer mon template en base de données avec une table "phrase" ressemblant à ça :

Nom, Age, Ville, Departement, Region, Pays, Taille, Poids, Cheveux, Yeux, Profession, Formation en enum "oui"/"non" en primary index
et template avec le résultat

Et à créer une requête where 'Nom'='oui' and 'age'='non',... généré simplement :

$i=0;$conditions='';
foreach ($info as $k=>$v)
{
       if($i!=0){$conditions=' AND ';}
       $conditions="`".$k."`=";
       if(!empty($v)){$conditions.="'oui'";}else{$conditions.="'non'";}
}
$rq="select template from phrase where ".$conditions;
$ressource=mysqli->query($rq);
$mysql=$ressource->fetch_assoc;
$template=$mysql['template'];
unset ($ressource);unset($mysql);


Et puis on remplace Smiley langue
Lothindil a écrit :

Son gros point positifi est de permettre un dédoublement du template, voire une multiplication (gestion sexe + langue par exemple) en fonction d'un (ou de plusieurs) champs de user tout en étant plus clair. J'avoue trouver ça plus clair :

...


que
...


ou que
...


que ça soit à maintenir, à mettre à jour ou à compléter. Smiley langue


C'est ridicule, tu imbriques la gestion de la langue dans le système de template. Ça n'a rien à faire là.

Lothindil a écrit :

Après, avec des dizaines de variables...


C'est le sujet du topic.