Aller au contenu

Simplifier un enchaînement de if et else


Lurch

Sujets conseillés

Bonjour,

Je suis en train de mettre en place ce genre de code :

<?
if ($abv == "10") { include('cas01.php');}
else
if ($abv == "11") { include('cas01.php');}
else
if ($abv == "200") { include('cas01.php');}
else
if ($abv == "15") { include('cas02.php');}
else
if ($abv == "397") { include('cas02.php');}
else include('cas00.php'); ?>  

Je cherche à alléger ce bout de code en regroupant les conditions par réponses (cas01, cas02) car cela va donner des listings trop lourds et probablement ralentir le site à la longue.

Je pense que c'est possible mais je ne connais pas la syntaxe pour résoudre cette question.

Merci d'avance ! ;)

Lien vers le commentaire
Partager sur d’autres sites

<?php
$map = array(
    '10'    => 'cas01.php'   ,
    '11'    => 'cas01.php'   ,
    '200'  => 'cas01.php'   ,
    '15'    => 'cas02.php'   ,
    '397'  => 'cas02.php'   ,
);
$default = 'cas01.php' :


if (isset($map['abv'])) {
       include($map['abv']);
} else {
       include($default);
}

Je donne ça pour faciliter la maintenance, coté vitesse je doute que tu fasses vraiment une différence à moins de milliers de lignes, et encore.

(et pitié, ne lui conseillez pas l'horrible switch utilisé à contre-sens)

Lien vers le commentaire
Partager sur d’autres sites

OK

Je pense que ça va le faire (en mettant plutôt $default = 'cas00.php' ;) )

Voilà qui devrait me faire gagner du temps.

Merci !

Lurch

Lien vers le commentaire
Partager sur d’autres sites

Ca ne changera pas grand chose mais il y a aussi ceci :

switch ($abv) {
  case "10":
     include('cas01.php');
  break;
  case "11":
     include('cas01.php');
  break;
  case "200":
     include('cas01.php');
  break;
  case "15":
     include('cas02.php');
  break;
  case "397":
     include('cas02.php');
  break;

  default:
     include('cas00.php');
}

Mais la méthode de Ganf me semble la mieux point de vue 'entretien' ^_^

A toute

Portekoi

Modifié par portekoi
Lien vers le commentaire
Partager sur d’autres sites

Mais en quoi un switch ou un elsif serait "horrible" ...

@Granf>Ta technique est "correcte" mais comparée à un if/elseif/else ou un switch elle est plutôt dispendieuse au niveau de la mémoire. Effectivement pour quelques cas (peu de valeurs) c'est juste elle ne fait pas de différence, toutefois tu alloue de la mémoire pour chaque cas alors qu'un seul ne sera juste, dans le cas d'un swtich ou d'un if/elseif lorsqu'un cas est traité les autres ne sont pas évalués...

Cela ne semble pas critique à première vue, mais sur un environnement ou tu ne gère pas la mémoire "toi-même" (par exemple, hébergement mutualisé, ...) cela peut avoir des conséquences...

Personnellement, j'utilise le plus souvent des if/elseif en général... mais bon j'admets que la raison que j'évoque vise des cas "extrêmes"...

*EDIT*

Deplus dans le cas évoqué par Lurch, j'utiliserait un -> || ou OR pour les cas ou l'include est le même...

<?php
if($abv == "10" || $abv == "11" || $abv == "200") {
 include('cas01.php');
} elseif($abv == "15" || $abv == "397") {
 include('cas02.php');
} else {
 include('cas00.php');
}
?>

*EDIT2*

Le switch se simplifie aussi, un peu :

<?php
switch ($abv) {
 case "10":
 case "11":
 case "200":
    include('cas01.php');
    break;
 case "15":
 case "397":
    include('cas02.php');
    break;
 default:
    include('cas00.php');
}
?>

Modifié par TheRec
Lien vers le commentaire
Partager sur d’autres sites

_AT_TheRec: je n'ai rien contre le elseif (même si je préfererai probablement faire un elseif par cas plutot que d'utiliser comme toi un opérateur logique pour cumuler les conditions)

Je n'ai même rien contre ton switch. Ce qui me gêne c'est le switch donné par portekoi, celui que j'appelle "utilisé à contresens". Le switch est fait pour avoir des clauses globalement cumulables et non exclusives. Il est malheureusement trop utilisé à la place des elseif alors qu'en PHP il n'offre que des désavantages (il n'est pas plus rapide mais par contre il est une horreur en maintenance à cause de la syntaxe différentes des autres structures et du fait qu'un "break" oublié ne se voit pas forcément)

Pour la mémoire, franchement, même si tu avais quelques centaine de cas, tu ne verras vraiment pas la différence. On parle là d'un ou deux ko, pas plus. Comme il ne dépassera pas la centaine, on peut largement oublier tout ça. Si je propose cette méthode par tableau c'est qu'elle est nettement plus efficace à maintenir et à manipuler.

D'ailleurs, si vraiment tu t'occupes des perfs, passer par un tableau ici s'avère probablement plus rapide qu'une suite de test, même si l'intuition tend à dire le contraire. Avec un bon cache d'opcode mon tableau est quasi considéré comme du statique et je n'ai qu'une résolution d'index de tableau au lieu d'une suite de tests/branchements. J'utilise quelques octets de mémoire mais je les occupe moins longtemps et avec moins de proc. Au final je ne garantis vraiment pas que ma solution est la moins optimisée.

Enfin bon, je ne sais même pas pourquoi on parle de mémoire et de perf sur ce genre de code. Si vous en êtes à optimiser à ce point là ce n'est plus en PHP qu'il faut vous pencher. Et franchement j'ai très rarement vu des raisons de se pencher sur ce genre de détails de perf. Sorti de Yahoo et d'une centaine de sites dans le monde, je pense qu'on peut oublier tout ça.

Lien vers le commentaire
Partager sur d’autres sites

Heu... Ne vous battez pas ! :lol:

Bon, rapidement car plutôt fatigué : j'ai testé la solution Ganf mais ça ne fonctionne pas.

Je testerai d'ici lundi celle(s) de TheRec en relisant à fond vos posts et je dirai si ça colle de façon à ce que cela puisse servir à la communauté des nioubiz en php. ;)

Merci !

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

Effectivement, le switch était optimisable mais je ne suis pas d'accord sur l'histoire du Break oublié car dans ce cas ,tu te mets en ASP comme ca, tu pourras oublier les ';' .

Le break est là pour remplacer, à mon sens, les if successif.

Maintenant, il est vrai qu'à ce niveua là, ca ne joue vraiment pas un rôle majeur.

Sinon, on passe en POO. :)

++

Portekoi

Lien vers le commentaire
Partager sur d’autres sites

<?php
$map = array(
    '10'    => 'cas01.php'   ,
    '11'    => 'cas01.php'   ,
    '200'  => 'cas01.php'   ,
    '15'    => 'cas02.php'   ,
    '397'  => 'cas02.php'   ,
);
$default = 'cas01.php' :
if (isset($map['abv'])) {
       include($map['abv']);
} else {
       include($default);
}

Je donne ça pour faciliter la maintenance, coté vitesse je doute que tu fasses vraiment une différence à moins de milliers de lignes, et encore.

(et pitié, ne lui conseillez pas l'horrible switch utilisé à contre-sens)

<{POST_SNAPBACK}>

Lurch,

Si la méthode de Ganf ne marche pas, c'est parce que ton serveur considère toute variable comme 'existante' par défaut. Donc, il fais tous les cas, puisque :

if (isset($map['abv'])) {

est toujours évalué en 'TRUE' (vrai).

Ceci dit, elle est 'valable' et logique. Tu devrais juste remplacer cette ligne par :

if (!empty($map['abv'])) {

C'est moins logique, mais ca doit marcher :)

PS : De la même facon que :

- Lorsque Dan poste une expression regulière qui ne marche pas je ne me pose pas la question "Où a t il fait une erreur", mais "pourquoi ca marche, mais pas chez moi",

de la même façon je ne remettrais pas en cause le code de Ganf, au plus je me poserais la question de savoir pourquoi ca veut pas marcher chez moi :(

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

J'aurais tendance à remplacer

if (isset($map['abv'])) {
      include($map['abv']);

par

if (isset($map[$abv])) {
      include($map[$abv]);

$abv est bien une variable... pas une constante littérale, non ?

Mais comme chaque fois que Ganf poste du code, je ne me demande pas non plus s'il est correct, il l'est par définition. :)

Dan

Lien vers le commentaire
Partager sur d’autres sites

PS : De la même facon que :

- Lorsque Dan poste une expression regulière qui ne marche pas je ne me pose pas la question "Où a t il fait une erreur", mais "pourquoi ca marche, mais pas chez moi",

de la même façon je ne remettrais pas en cause le code de Ganf, au plus je me poserais la question de savoir pourquoi ca veut pas marcher chez moi :(

<{POST_SNAPBACK}>

Hou ! J'ai laissé entendre que je mettais en cause le code de Ganf ? Oups je vais me relire car ce n'est pas du tout mon état d'esprit. Alors mon clavier a peut-être fourné quelque part.

Bon encore une fois merci à tous, j'ai de quoi faire pour quelques heures :)

Lien vers le commentaire
Partager sur d’autres sites

Euh, je vous en prie, remettez en cause mes codes, d'autant que j'ai l'habitude de faire beaucoup de fautes en première frappe. Visiblement il y en avait une belle (cf post de Dan).

_AT_Anonymous: aucune configuration que je connaisse pourrait faire que PHP considère toute variable comme existante. Il peut éventuellement renvoyer une valeur pour une variable inexistante (valeur NULL) mais isset() répondra bien false.

_AT_portekoi: la différence c'est que si j'oublie un point virgule j'ai une erreur de syntaxe. Si j'oublie un break non seulement je n'ai pas d'erreur, mais ça peut sembler marcher lors de mes tests, et surtout je ne serai pas capable de voir une quelconque erreur quelques jours après parce qu'il est naturel qu'un switch n'ai pas de break. Il n'y a rien de dramatique mais le privilégie toujours les formes de syntaxe standard, qui facilitent beaucoup moins les erreurs.

Lien vers le commentaire
Partager sur d’autres sites

Visiblement il y en avait une belle (cf post de Dan).

Tu m'en vois ravi !

J'avais du mal à comprendre à première lecture et pourtant j'ai quelques lignes de Php dans les bras.

J'ai gagné un bouquin dédicacé ? :lol:

Lien vers le commentaire
Partager sur d’autres sites

_AT_Ganf> Je parlais d'un principe de programmation... une suite de tests sera plus efficace qu'un tableau du simple point de vue que le stockage en mémoire (même en cache) est plus lent que l'évaluation d'une condition, dans ton cas tu stockes tous les cas dans un tableau, alors qu'un seul cas sera juste normalement dans notre cas de figure...le elseif arrêtera la comparaison avant d'avoir effectuer toutes les comparaisons (à moins le dernière branche de la liste soit vérifée ou que la branche par défaut soit utilisée).

En gros je répète ce que j'ai dit plus haut... peu de cas, ta solution est très appropriée bien que dans un plus grand nombre de cas les elseif, je propose donc qu'on close la discussion sur ces optimisation de boutiquiers, on n'a pas l'occasion de réellement en tirer les avantages dans ce cas de figure.

Juste pour éclaircir un point, pourquoi tu n'utiliserais pas d'opérateurs logiques dans ces conditions ? L'avantage de ces opérateurs et que les cas sont évalués les un après les autres et la condition "global" est retournée dès qu'un cas est vérifié (les autres qui le suivent ne sont pas évalué, dans une suite de OR, c'est un optimisation que presque tous les language utilisent...) le cas du OR n'est pas réellement parlante, mais une combinaison de AND et OR peuvent démontrer cette optimisation...

Désolé d'avoir détourné un peu ce sujet...je dirais que toutes ces solutions se valent, mais ce n'est que mon avis ;)

Lien vers le commentaire
Partager sur d’autres sites

_AT_Ganf> Je parlais d'un principe de programmation...

J'ai bien compris, mais attention aux principes de programmation quand on les applique à des langages de script. Certaines choses s'inversent assez facilement.

Cette astuce de tableau est connue pour être plus rapide en PHP que la suite de elseif (sur une liste d'un nombre conséquent d'éléments). Je n'ai pas cherché pourquoi ici mais je ne serai pas étonné qu'il s'agisse du temps nécessaire à PHP pour aller chercher une variable dans sa table de hash.

Ton elseif arrête effectivement la comparaison avant la fin mais en réalité ça n'économise rien. Ce qui coute cher ce n'est pas tant le test, c'est la conversion en code machine et l'analyse pour descendre à la fin de la condition. L'optique tableau fait elle aussi une seule comparaison (et pas une avec chaque élément) mais sera plus simple à interpréter.

La règle de base est de toutes façons toujours "ne jamais faire des optimisations de syntaxe". C'est encore plus vrai en langage de script car si tu prend ce genre de langage c'est bien pour favoriser la lisibilité et le code source sur les performances. Il est aussi assez rare qu'une optimisation de syntaxe gagne grand chose sur du code interprété.

Juste pour éclaircir un point, pourquoi tu n'utiliserais pas d'opérateurs logiques dans ces conditions ? L'avantage de  ces opérateurs et que les cas sont évalués les un après les autres et la condition "global" est retournée dès qu'un cas est vérifié (les autres qui le suivent ne sont pas évalué, dans une suite de OR, c'est un optimisation que presque tous les language utilisent...) le cas du OR n'est pas réellement parlante, mais une combinaison de AND et OR peuvent démontrer cette optimisation...

Argh, en fait il faudrait le placarder partout : "ne jamais faire des optimisations de syntaxe". Quand tu sacrifies la lisibilité pour un quart de microseconde (ça doit être à peu près ce que tu gagnes ici dans les meilleurs jours) ça te retombes toujours sur le coin de la figure.

C'est encore plus vrai sur un langage de script où gagner quatre octets de mémoire (cas du tableau) ou 4 opcode (regrouper des cas) n'a strictement aucune influence sur le déroulement global du script (oui, même avec plein de ce genre d'optimisations partout on ne gagnera vraiment pas de quoi payer le développeur qui fait ces optimisations).

C'est encore on ne peut plus vrai avec PHP, qui a souvent des effets contraires à ce que la plupart des développeurs attendent. Vous saviez que l'accès à une constante est plus lent que l'accès à une variable en PHP ? qu'une référence ne fait pas gagner en vitesse la plupart du temps contrairement aux autres langages ?

De plus je doute fortement que tu aies une quelconque optimisation ici. Que tu utilises un or ou un elseif, les deux s'arrêteront à la première expression vraie. Il n'y a pas plus de calculs dans l'un que dans l'autre.

Ce qui me gêne dans la solution de regrouper plusieurs cas dans un elseif c'est la lisibilité et la maintenance. Pour voir ce que fait tel ou tel cas on est obligé de "décoder". Si on a un cas par ligne, avec des syntaxes très très proches pour chaque ligne, l'oeil voit globalement ce qu'il se passe. Si tu as une expression différente dans chaque elseif ça devient moins clair.

Si réellement on veut associer plusieurs cas ensemble, alors pour le coup un switch est plus logique (vous voyez ? j'aime bien les switch, ce que je n'aime pas ce sont les switch qui sont avec un break à chaque cas).

Mais bon, la lisibilité c'est tout à fait subjectif, si tu trouves ça plus clair libre à toi d'utiliser mais franchement oublies ces questions "d'optimisation"

Lien vers le commentaire
Partager sur d’autres sites

D'ailleurs, si vraiment tu t'occupes des perfs, passer par un tableau ici s'avère probablement plus rapide qu'une suite de test, même si l'intuition tend à dire le contraire.

Je ne sais pas comment est fait l'optimisateur de PHP, mais n'importe quel optimiseur un peu civilise convertira de lui-meme un gros switch/case en tableau ...

Et franchement j'ai très rarement vu des raisons de se pencher sur ce genre de détails de perf. Sorti de Yahoo et d'une centaine de sites dans le monde, je pense qu'on peut oublier tout ça.

<{POST_SNAPBACK}>

... Ouai, c'est pour ca qu'il faut la puissance d'un super calculateur d'il y a 20 ans pour faire tourner un 'simple' traitement de texte de nos jours :evil: M'enfin, c'est un autre debat.

Ce qui est claire, c'est que je ne vais pas perdre mon temps a cherche la micro seconde, mais je ne vais pas faire non plus une grosse bouse en disant "j'ai le CPU derriere" ... ca fini toujours tres mal dans le temps ^_^

Modifié par destroyedlolo
Lien vers le commentaire
Partager sur d’autres sites

... Ouai, c'est pour ca qu'il faut la puissance d'un super calculateur d'il y a 20 ans pour faire tourner un 'simple' traitement de texte de nos jours  :evil: M'enfin, c'est un autre debat.

<{POST_SNAPBACK}>

Pas faux ;)

Concernant le tableau, effectviement il y a trasposition dans un hash table l'accès sera beaucoup plus rapide. Mais là j'avoue la limite de mes connaissances, je n'ai pas assez étudié le core de PHP ou un optimizer PHP pour tirer ces conclusions. Je pense que la prochaine fois j'utiliserais cette technique de tableau et je vous remercie pour ces info ;)

Lien vers le commentaire
Partager sur d’autres sites

Veuillez vous connecter pour commenter

Vous pourrez laisser un commentaire après vous êtes connecté.



Connectez-vous maintenant
×
×
  • Créer...