Un moyen de casser la déclaration if en PHP?

129

Existe-t-il une commande en PHP pour arrêter d'exécuter l'instruction courante ou parente if, identique à breakou break(1)pour switch/ loop. Par exemple

$arr=array('a','b');
foreach($arr as $val)
{
  break;
  echo "test";
}

echo "finish";

dans le code ci-dessus, PHP ne fera pas echo "test";et ira àecho "finish";

J'ai besoin de ça pour si

$a="test";
if("test"==$a)
{
  break;
  echo "yes"; // I don't want this line or lines after to be executed, without using another if
}
echo "finish";

Je veux breakla ifdéclaration ci-dessus et arrêter l'exécution de echo "yes";tels codes qui ne sont plus nécessaires pour être exécutés, il peut y avoir ou non une condition supplémentaire, y a-t-il un moyen de le faire?

Mise à jour: Seulement 2 ans après avoir posé cette question, j'ai grandi, j'ai appris comment le code peut être écrit en petits morceaux, pourquoi les if imbriqués peuvent être une odeur de code et comment éviter de tels problèmes en premier lieu en écrivant de petites fonctions gérables.

Muhammad Usman
la source
15
Aucun de vos exemples n'a de sens logiquement.
Tim Pietzcker
1
@Usman: S'il n'y a pas de condition, alors le echo(dans votre exemple) ne sera jamais exécuté. Vous pouvez donc tout aussi bien le supprimer.
Oliver Charlesworth
2
N'est-ce pas try catchune option?
giannis christofakis
J'ai d'abord pensé que Tim était juste impoli ... Mais ensuite, j'ai pensé qu'il avait raison ... Pourquoi auriez-vous du code derrière une pause inconditionnelle? Débogage? J'aime sortir des boucles for avec continue; Et ce serait bien de briser les requêtes très difficiles avec une commande "juste arrêter ici" ...if (condition) { if ( oneothercondition ) stop; if ( yetothercondition ) stop; // go ahead , all is fine }
Joeri
@Joeri je ne connais pas les premières idées de Muhhamad pourquoi il avait besoin d'une pause; Mais dans mon cas maintenant, c'est à des fins de débogage, non. Dans certains cas, cela permettrait de gagner du temps. Dans les cas où il n'est pas possible d'ajouter des points d'arrêt (lorsque vous n'utilisez pas d'IDE et / ou que vous devez travailler sur un site en direct pour certaines raisons, etc.)
Viktor Borítás

Réponses:

216

Ne vous inquiétez pas des commentaires des autres utilisateurs, je peux vous comprendre, PARFOIS, lors du développement de ce "chic", des choses sont nécessaires . Si nous pouvons casser un if, beaucoup de if imbriqués ne seront pas nécessaires, ce qui rendra le code beaucoup plus propre et esthétique.

Cet exemple de code illustre que CERTAINES SITUATIONS où interrompues si peuvent être beaucoup plus appropriées que beaucoup de si imbriqués laids ... si vous n'avez pas fait face à cette certaine situation ne signifie pas qu'elle n'existe pas .

Code laid

if(process_x()) {

    /* do a lot of other things */

    if(process_y()) {

         /* do a lot of other things */

         if(process_z()) {

              /* do a lot of other things */
              /* SUCCESS */

         }
         else {

              clean_all_processes();

         }

    }
    else {

         clean_all_processes();

    }

}
else {

    clean_all_processes();

}

Beau code

do {

  if( !process_x() )
    { clean_all_processes();  break; }

  /* do a lot of other things */

  if( !process_y() )
    { clean_all_processes();  break; }

  /* do a lot of other things */

  if( !process_z() )
    { clean_all_processes();  break; }

  /* do a lot of other things */
  /* SUCCESS */

} while (0);

Comme le dit @NiematojakTomasz, l'utilisation de gotoest une alternative, la mauvaise chose à ce sujet est que vous devez toujours définir l'étiquette (cible de point).

AgelessEssence
la source
29
Génial! Parfois, les questions sont mal comprises en raison de leur sens profond. Vous l'avez parfaitement, j'ai besoin d'un code propre pour éviter de suivre la fin deif
Muhammad Usman
4
J'avais besoin d'exécuter le même code après chaque test réussi (environ 3 ou 4 tests), et de mettre un elseifsur chaque test échoué. C'est exactement ce que je cherchais, maintenant mon code est compatible KISS et DRY :) Merci!
s3v3n
3
Mec, c'est sale! Mais il obtient mon vote positif .. Je travaille sur un système sale;)
LeonardChallis
8
@rdlowrey, la conversation est gratuite, alors VEUILLEZ nous montrer un exemple de "POO bien écrite" pour résoudre la question OP: 3
AgelessEssence
7
Ne confondez pas la demande de sample avec des attaques personnelles ... en fait, il vous manque quelque chose d'important, tout le codage ne devrait pas être OOP, c'est une chose insensée d'écrire des tâches simples avec la magie * de la POO.
AgelessEssence
98

Encapsulez votre code dans une fonction. Vous pouvez arrêter d'exécuter une fonction avec returnà tout moment.

Maxim Krizhanovsky
la source
2
Je pensais que tu voulais un si, pas une fonction? ;)
Arnaud Le Blanc
3
@ arnaud576875 si le code est dans une fonction, vous pouvez utiliser return dans l'instruction if, pour interrompre l'exécution.
Maxim Krizhanovsky
1
Une fonction doit avoir "1 entrée" et "1 sortie". Les retours multiples sont bâclés et sujets aux erreurs.
Old Man Walter
@OldManWalter Cela n'est vrai que pour renvoyer des données réelles. Cependant, la gestion des erreurs est une exception courante à cette règle. Une exception de jet ou un retour faux à plusieurs endroits sont parfaitement acceptables sans toucher aux pièges courants contre lesquels la mentalité «1 entrée, 1 sortie» tente de se protéger.
danielson317
41

bonne façon de faire ceci:

try{
    if( !process_x() ){
        throw new Exception('process_x failed');
    }

    /* do a lot of other things */

    if( !process_y() ){
        throw new Exception('process_y failed');
    }

    /* do a lot of other things */

    if( !process_z() ){
        throw new Exception('process_z failed');
    }

    /* do a lot of other things */
    /* SUCCESS */
}catch(Exception $ex){
    clean_all_processes();
}

Après avoir lu certains des commentaires, j'ai réalisé que la gestion des exceptions n'a pas toujours de sens pour le contrôle de flux normal. Pour un flux de contrôle normal, il est préférable d'utiliser "If else":

try{
  if( process_x() && process_y() && process_z() ) {
    // all processes successful
    // do something
  } else {
    //one of the processes failed
    clean_all_processes();
  }
}catch(Exception ex){
  // one of the processes raised an exception
  clean_all_processes();
}

Vous pouvez également enregistrer les valeurs de retour du processus dans des variables, puis archiver les blocs d'échec / d'exception dont le processus a échoué.

Rahul Ranjan
la source
1
Les exceptions peuvent être utiles dans ce cas, mais il semble que vous les utilisez à mauvais escient. Les exceptions sont exceptionnelles, pas pour le déroulement normal du programme. Si l'échec est exceptionnel, le process_x-z doit lever l'exception par lui-même; clean_all_processes () serait mieux dans un bloc finally car c'est un nettoyage qui doit être fait de toute façon.
Jimmy T.
J'ai amélioré la solution.
Rahul Ranjan
La raison pour laquelle je n'ai finalement pas utilisé est, il n'est pas pris en charge jusqu'à php5.5
Rahul Ranjan
20

Parce que vous pouvez sortir d'un do / while, laissez - nous « faire » un tour. Avec un while (faux) à la fin, la condition n'est jamais vraie et ne se répétera pas, encore une fois.

do
{
    $subjectText = trim(filter_input(INPUT_POST, 'subject'));
    if(!$subjectText)
    {
        $smallInfo = 'Please give a subject.';
        break;
    }

    $messageText = trim(filter_input(INPUT_POST, 'message'));
    if(!$messageText)
    {
        $smallInfo = 'Please supply a message.';
        break;
    }
} while(false);
Markus Zeller
la source
Personne ne dit que vous devez utiliser cela. C'est juste un exemple pour «éclater».
Markus Zeller
2
Approche ordonnée - fait le travail.
benjaminhull
16

aller :

L' opérateur goto peut être utilisé pour passer à une autre section du programme. Le point cible est spécifié par une étiquette suivie de deux-points et l'instruction est donnée comme goto suivi de l'étiquette cible souhaitée. Ce n'est pas un goto complet et illimité . L'étiquette cible doit être dans le même fichier et le même contexte, ce qui signifie que vous ne pouvez pas sauter hors d'une fonction ou d'une méthode, ni sauter dans une. Vous ne pouvez pas non plus sauter dans aucune sorte de structure de boucle ou de commutateur. Vous pouvez sauter hors de ceux-ci, et une utilisation courante consiste à utiliser un goto à la place d'une pause à plusieurs niveaux ...

NiematojakTomasz
la source
82
Chaque fois que vous utilisez goto, le bébé Jésus mange un chaton. Aussi, xkcd.com/292
12
Désolé d'être cohérent. J'ai référencé une page de manuel php expliquant l'utilisation exacte du mot-clé mentionné. Et même si c'est une solution sale, c'est toujours la bonne solution.
NiematojakTomasz
3
Je ne comprends pas exactement en quoi ce n'est pas une bonne pratique de le faire? C'est beaucoup plus simple que toutes les autres solutions?
538ROMEO
1
D'accord avec Sébastien. Dans certains cas, l'opérateur goto est très utile et simple.
Jerry
6
Ne vous inquiétez pas, les programmeurs vous feront toujours sentir que vous ne codez pas correctement et que nous voulons que nous codions comme eux. C'est encore plus vrai dans la communauté php car nous sommes un groupe de codeurs hipster et PHP nous donne ces mots-clés de liberté et la liberté de porter un jugement sur la façon dont chacun fait les choses. J'ai utilisé (pas beaucoup) le gotomot - clé dans les codes de production et je n'ai jamais eu de problèmes.
vdegenne
7

Il existe une commande: goto

if(smth) {
   .....
   .....
   .....
   .....
   .....
   goto Area1;
   .....
   .....


}



Area1:
....your code here....

Cependant, rappelez goto- vous n'est pas une pratique recommandée, car cela rend le code à être formaté de manière inhabituelle.

T.Todua
la source
1
J'ai testé ce script, le code ci-dessous goto Area1; ne sera pas exécuté.
Leon Armstrong
5

Non, il n'y a aucun moyen de "casser" un bloc if comme vous le feriez à l'intérieur de boucles. :(
Alors transformez votre test en un switch!

Je me demande pourquoi personne ne vous a encouragé à utiliser l' instruction switch depuis (même si vous n'avez pas beaucoup de cas de test)
Pensez-vous que c'est trop verbeux?

J'irais certainement ici

  switch($a){
    case 'test':
        # do stuff here ...
        if(/* Reason why you may break */){
           break; # this will prevent executing "echo 'yes';" statement
        }
        echo 'yes';  # ...           
        break; # As one may already know, we might always have to break at the end of case to prevent executing following cases instructions.
    # default:
        # something else here  ..
        # break;
  }

Pour moi, les exceptions sont destinées à soulever des erreurs et pas vraiment à contrôler les défauts d'exécution.
Si le comportement de rupture que vous essayez de définir ne concerne pas les erreurs inattendues, la gestion des exceptions n'est pas la bonne solution ici :/.

Stéphane
la source
Idée intéressante mais je ne l'utiliserais pas pour du "vrai" code.
Jimmy T.
1
"réel", que voulez-vous dire? :/
Stphane
1
@Stphane Un commentaire tardif, mais l'utilisation d'un interrupteur dans cette situation va à l'encontre du principe du moindre étonnement. Une instruction switch est censée contrôler la sélection des données et non contrôler le déroulement du programme.
FWDekker
« Switch compare une expression à différentes valeurs et exécute un bloc de code spécifique en fonction de la valeur à laquelle l'expression est égale.» Ensuite, chaque bloc peut évaluer des expressions subsidiaires qui à leur tour peuvent demander au flux d'exécution de renvoyer ou d'ignorer certaines instructions ... Je ne pense pas que le commutateur irait à l'encontre du principe du moindre étonnement dans ce cas d'utilisation très restreint mais, ceci dit, le contexte d'origine et les exigences peuvent en effet nécessiter une refactorisation.
Stphane
4
$a = 1;

switch($a) {

  case "1":

    if  ($condition1){
      break;
    }

    if  ($condition2){
      break;
    }

    if  ($condition3){
      break;
    }
}

De cette façon, j'ai ce que je veux. J'utilise un interrupteur qui n'a qu'un cas défini, puis j'utilise break au cas où choisir si condition. La raison pour laquelle j'utilise la rupture: condition1 et condition2 peuvent toutes deux satisfaire, dans cette situation, seule la condition1 est appliquée .IF est sélectif en fonction de l'ordre.

user3530437
la source
8
Vous n'avez pas besoin de variable pour cela. Il suffit d'utiliserswitch(true) { case true:
Maxim Krizhanovsky
1

Non.

Mais que diriez-vous:

$a="test";
if("test"==$a)
{
  if ($someOtherCondition)
  {
    echo "yes";
  }
}
echo "finish";
Oliver Charlesworth
la source
3
Merci, mais je recherche une version plus simple pour éviter trop de ifdéclarations
Muhammad Usman
2
@Usman: Si vous avez plusieurs conditions, vous devez les vérifier. Vérifier une condition implique traditionnellement une ifdéclaration. Je ne sais pas comment vous comptez éviter cela.
Oliver Charlesworth
1

Déplacez simplement le code qui n'est pas censé être exécuté vers la else/elseifbranche. Je ne vois pas vraiment pourquoi voudriez-vous faire ce que vous essayez de faire.

Mchl
la source
1

La réponse simple est que non, il n'y a pas de moyen de rompre avec une ifinstruction sans arrêter complètement l'exécution (via exit). D'autres solutions ne fonctionneront pas pour moi car je ne peux pas changer la structure de l' ifinstruction, puisque j'injecte du code dans un plugin, comme ceci:

if ( condition ) {
  // Code and variables I want to use

  // Code I have control over

  // Code I don't want to run
}
// More code I want to use
David
la source
0

En réponse à votre question de savoir si cela est réalisable ou non, alors oui, c'est réalisable en utilisant l'opérateur "goto" de php.

Mais éthiquement, ce n'est pas une bonne pratique d'utiliser "goto" et s'il est nécessaire d'utiliser goto, cela signifie que le code doit être reconstruit de sorte que l'exigence de goto puisse être supprimée.

Selon l'exemple de code que vous avez publié ci-dessus, il est clairement visible que le code peut être reconstruit et que le code qui n'est plus nécessaire peut être supprimé ou commenté (si la possibilité existe pour une utilisation future).

Sandeep Garg
la source
0
$arr=array('test','go for it');
$a='test';
foreach($arr as $val){
  $output = 'test';
  if($val === $a) $output = "";
  echo $output;
}
echo "finish";

en combinant vos déclarations, je pense que cela vous donnerait le résultat souhaité. propre et simple, sans avoir trop de déclarations.

pour le code laid et beau, ma recommandation serait:

function myfunction(){
  if( !process_x() || !process_y() || !process_z()) {
    clean_all_processes();  
    return; 
  }
/*do all the stuff you need to do*/
}

quelque part dans votre code normal

myfunction();
Arthur Kielbasa
la source
0

Je pense que vous recherchez ceci:

if (condition) { 
    if ( oneothercondition ) continue;  
    if ( yetothercondition ) continue; 

    // go ahead , all is fine
}

Le manuel php montre des forexemples, mais je pense que cela fonctionne aussi pourif

Joeri
la source
-1

J'ai une solution simple sans beaucoup de changements. la déclaration initiale est

Je veux casser l'instruction if ci-dessus et arrêter d'exécuter echo "yes"; ou de tels codes dont l'exécution n'est plus nécessaire, il peut y avoir ou non une condition supplémentaire, y a-t-il moyen de le faire?

donc, cela semble simple. essayez un code comme celui-ci.

$a="test";
if("test"==$a)
{
  if (1==0){
      echo "yes"; // this line while never be executed. 
      // and can be reexecuted simply by changing if (1==0) to if (1==1) 
  }
}
echo "finish";

si vous voulez essayer sans ce code, c'est simple. et vous pouvez revenir quand vous le souhaitez. une autre solution est les blocs de commentaires. ou simplement penser et essayer dans un autre code séparé et copier-coller uniquement le résultat dans votre code final. et si un code n'est plus nécessaire, dans votre cas, le résultat peut être

$a="test";
echo "finish";

avec ce code, la déclaration d'origine est totalement respectée .. :) et plus lisible!

christian audebert
la source
-2

La solution simple est de le commenter.

$a="test";
if("test"==$a)
{

  //echo "yes"; //no longer needed - 7/7/2014 - updateded bla bla to do foo
}

L'avantage supplémentaire est que vous ne modifiez pas votre code d'origine et que vous pouvez le dater, le parapher et en indiquer la raison.

Pourquoi voter contre, selon la demande du PO, je pense que c'est une solution parfaitement valable.

"Je veux [casser l'instruction if ci-dessus et] arrêter d'exécuter echo" yes "; ou de tels codes qui ne sont plus nécessaires pour être exécutés, il peut y avoir ou non une condition supplémentaire, y a-t-il un moyen de le faire?"

En fait, quelqu'un pourrait examiner certaines des autres solutions, un an plus tard, et se demander ce qui se passe là-bas. Selon ma suggestion, on pourrait laisser une bonne documentation pour référence future, ce qui est toujours une bonne pratique.

ArtistiquePhoenix
la source
2
Cela ne résout pas le problème. La pause pourrait aussi être dans un si.
Jimmy T.
Vous ne pouvez pas commenter dans une déclaration if? Ou commenter un? Voulez-vous dire utiliser un if pour exclure l'exécution? Si oui, quel est le but de la rupture, n'est-ce pas si les déclarations sont faites? Commentez-le aussi. Désolé, mais ne voyez pas votre point.
ArtisticPhoenix
Quelque chose comme ceci: a: if ("test" == $ a) {... if (...) break a; ...}
Jimmy T.
-3

Qu'en est-il de l'utilisation de l'opérateur ternaire?

<?php
 // Example usage for: Ternary Operator
 $action = (empty($_POST['action'])) ? 'default' : $_POST['action'];
?>

Ce qui est identique à cette instruction if / else:

<?php
 if (empty($_POST['action'])) {
   $action = 'default';
 } else {
   $action = $_POST['action'];
 }
?>
Martin Stone
la source
En PHP7:$a = $_POST['action'] ?? 'default';
Tobias Mühl
-3

Pour arrêter complètement l'exécution du reste du script, vous pouvez simplement faire

sortie; // À la place de la pause. Le reste du code ne s'exécutera pas

marque kasina
la source
-4

Je suis en retard à la fête mais je voulais contribuer. Je suis surpris que personne n'ait suggéré exit(). C'est bon pour les tests. Je l'utilise tout le temps et fonctionne comme du charme.

$a ='';
$b ='';
if($a == $b){
echo 'Clark Kent is Superman';
exit();
echo 'Clark Kent was never Superman';
}

Le code s'arrêtera à exit()et tout ce qui suit ne fonctionnera pas.

Résultat

Clark Kent is Superman

Cela fonctionne aussi bien avec foreach()et while(). Cela fonctionne partout où vous le placez vraiment.

foreach($arr as $val)
{
  exit();
  echo "test";
}

echo "finish";

Résultat

nothing gets printed here.

Utilisez-le avec un forloop()

for ($x = 2; $x < 12; $x++) {
    echo "Gru has $x minions <br>";
    if($x == 4){
    exit();
    }
}

Résultat

Gru has 2 minions
Gru has 3 minions
Gru has 4 minions

Dans un scénario normal

$a ='Make hot chocolate great again!';
echo $a;
exit();
$b = 'I eat chocolate and make Charlie at the Factory pay for it.';

Résultat

Make hot chocolate great again!
Combat de ballon
la source
-7
$a="test";
if("test"!=$a)
{
echo "yes";                   
}
 else
 {
  echo "finish";
}
Shanon
la source