Qualche modo per interrompere l'istruzione if in PHP?


129

Esiste un comando in PHP per interrompere l'esecuzione dell'istruzione corrente o parent if, uguale a breako break(1)per switch/ loop. Per esempio

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

echo "finish";

nel codice sopra PHP non lo farà echo "test";e andrà aecho "finish";

Ho bisogno di questo per se

$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";

Voglio breakla ifdichiarazione sopra e interrompere l'esecuzione echo "yes";o tali codici che non sono più necessari per essere eseguiti, potrebbe esserci o meno una condizione aggiuntiva, c'è modo di farlo?

Aggiornamento: Solo 2 anni dopo aver pubblicato questa domanda, sono cresciuto, ho imparato come il codice può essere scritto in piccoli blocchi, perché l'annidato se può essere un odore di codice e come evitare tali problemi in primo luogo scrivendo funzioni gestibili e piccole.


15
Nessuno dei tuoi esempi ha logicamente alcun senso.
Tim Pietzcker,

1
@Usman: se non c'è una condizione, il echo(nel tuo esempio) non verrà mai eseguito. Quindi potresti anche cancellarlo.
Oliver Charlesworth,

2
Non è try catchun'opzione?
giannis christofakis,

Prima ho pensato che Tim fosse solo maleducato ... Ma poi ho pensato che fosse corretto ... Perché dovresti avere un codice dietro un'interruzione incondizionata? Debug? Mi piace uscire per i loop con continue; E sarebbe bello interrompere domande molto difficili con un comando "fermati qui" ...if (condition) { if ( oneothercondition ) stop; if ( yetothercondition ) stop; // go ahead , all is fine }
Joeri

@Joeri non conosco le idee iniziali di Muhhamad sul perché avesse bisogno di una pausa; Ma nel mio caso ora ha scopi di debug, giusto. In alcuni casi risparmierebbe tempo. Nei casi in cui non è possibile aggiungere punti di interruzione (quando non si utilizza un IDE e / o si deve lavorare su un sito live per alcuni motivi, ecc.)
Viktor Borítás

Risposte:


216

Non preoccuparti dei commenti degli altri utenti, ti capisco, ALCUNI sono necessari quando si sviluppano queste cose "fantasiose" . Se riusciamo a rompere un if, molti if annidati non saranno necessari, rendendo il codice molto più pulito ed estetico.

Questo codice di esempio mostra che SITUAZIONI DI CERTAINE sono state interrotte se possono essere molto più adatte di un sacco di brutti nidi se ... se non hai affrontato quella determinata situazione non significa che non esiste .

Codice brutto

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();

}

Codice di bell'aspetto

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);

Come dice @NiematojakTomasz, l'uso di gotoè un'alternativa, la cosa brutta è che devi sempre definire l'etichetta (punto target).


29
Grande! A volte le domande vengono fraintese a causa del loro senso profondo. Hai capito perfettamente, ho bisogno di un codice pulito per evitare il monitoraggio della fine diif
Muhammad Usman,

4
Avevo bisogno di eseguire lo stesso codice dopo ogni test elseifandato a buon fine (circa 3 o 4 test) e inserirne uno su ogni test fallito. Questo è esattamente quello che stavo cercando, ora il mio codice è conforme a KISS e DRY :) Grazie!
s3v3n,

3
Amico, questo sembra sporco! Ma ottiene il mio voto .. Sto lavorando su un sistema sporco;)
LeonardChallis

8
@rdlowrey, il discorso è gratuito, quindi PER FAVORE mostraci un esempio di "OOP ben scritto" per risolvere la domanda OP: 3
AgelessEssence

7
Non confondere la richiesta del campione agli attacchi personali ... in effetti, ti stai perdendo qualcosa di importante, non tutto il codice dovrebbe essere OOP, è una cosa folle scrivere semplici compiti con la magia * di OOP.
AgelessEssence,

98

Incapsula il tuo codice in una funzione. È possibile interrompere l'esecuzione di una funzione returnin qualsiasi momento.


2
Pensavo volessi un se, non una funzione? ;)
Arnaud Le Blanc,

3
@ arnaud576875 se il codice è in una funzione, quindi è possibile utilizzare return nell'istruzione if per interrompere l'esecuzione.
Maxim Krizhanovsky,

1
Una funzione dovrebbe avere "1 way in" e "1 way out". RITORNI multipli è sciatto e soggetto a errori.
Old Man Walter,

@OldManWalter Questo è vero solo per la restituzione di dati effettivi. Tuttavia, la gestione degli errori è un'eccezione comune a questa regola. Un'eccezione di lancio o ritorno falso in più posizioni sono perfettamente accettabili senza colpire le insidie ​​comuni che la mentalità "1 entrata in, 1 uscita" sta cercando di proteggere.
danielson317,

41

modo corretto di fare questo:

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();
}

Dopo aver letto alcuni dei commenti, mi sono reso conto che la gestione delle eccezioni non ha sempre senso per il normale controllo del flusso. Per un normale flusso di controllo è meglio usare "Se altro":

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();
}

È inoltre possibile salvare i valori di ritorno del processo in variabili e quindi verificare nei blocchi di errori / eccezioni quale processo ha avuto esito negativo.


1
Le eccezioni possono essere utili in questi casi, ma sembra che le usi in modo improprio. Le eccezioni sono eccezionali, non per il normale flusso di programma. Se il fallimento è eccezionale, process_x-z dovrebbe generare l'eccezione da solo; clean_all_processes () sarebbe meglio in un blocco finally poiché è clean up che deve essere fatto comunque.
Jimmy T.

Ho migliorato la soluzione.
Rahul Ranjan,

Il motivo per cui non l'ho usato finalmente è, non è supportato fino a php5.5
Rahul Ranjan,

20

Perché si può rompere da un do / while, cerchiamo di " fare " un giro. Con un po '(falso) alla fine, la condizione non è mai vera e non si ripeterà più.

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);

Nessuno dice che devi usarlo. È solo un esempio per "scoppiare".
Markus Zeller,

2
Approccio ordinato - fa il lavoro.
benjaminhull,

16

vai :

L' operatore goto può essere usato per saltare ad un'altra sezione del programma. Il punto target viene specificato da un'etichetta seguita da due punti e l'istruzione viene data come goto seguita dall'etichetta target desiderata. Questo non è un goto completo e senza restrizioni . L'etichetta di destinazione deve trovarsi nello stesso file e contesto, il che significa che non è possibile saltare da una funzione o metodo, né è possibile saltare in uno. Inoltre, non puoi saltare in alcun tipo di loop o struttura di switch. Puoi saltare da questi e un uso comune è usare un goto al posto di una pausa multi-livello ...


82
Ogni volta che lo usi goto, Gesù Bambino mangia un gattino. Inoltre, xkcd.com/292

12
Mi dispiace per essere coerente. Ho fatto riferimento alla pagina di manuale di php che spiega l'uso esatto della parola chiave menzionata. E anche se è una soluzione sporca è comunque la soluzione corretta.
NiematojakTomasz,

3
Non capisco esattamente come non sia una buona pratica farlo? È molto più semplice di tutte le altre soluzioni?
538ROMEO

1
Concordato con Sébastien. In alcuni casi, l'operatore goto è molto utile e semplice.
Jerry,

6
Non preoccuparti, i programmatori ti faranno sempre sentire che non stai programmando correttamente e vogliono che noi programmiamo come loro. Questo è ancora più vero nella comunità di php perché siamo un gruppo di programmatori hipster e PHP ci dà queste parole chiave sulla libertà e la libertà di essere così giudicante su come tutti fanno le cose. Ho usato (non ampiamente) la gotoparola chiave nei codici di produzione e non ho mai avuto problemi.
vdegenne,

7

Esiste il comando: goto

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


}



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

Tuttavia, ricordare gotonon è una pratica consigliata, perché rende il codice da formattare in modo insolito.


1
Ho testato questo script, il codice sotto goto Area1; non verrà eseguito.
Leon Armstrong,


5

No, non c'è modo di "rompere" un blocco if come faresti nei loop. :(
Quindi trasforma il tuo test in un switch!

Mi chiedo perché nessuno ti abbia incoraggiato a usare l'istruzione switch poiché (anche se non hai molti casi di test)
Pensi che sia troppo prolisso?

Lo farei sicuramente qui

  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;
  }

Per me le eccezioni hanno lo scopo di generare errori e non di controllare realmente il difetto di esecuzione.
Se il comportamento di interruzione che si sta tentando di impostare non riguarda errori imprevisti, la gestione delle eccezioni non è la soluzione giusta qui :/.


Idea interessante ma non la userei per codice "reale".
Jimmy T.

1
"reale", cosa intendi? :/
Stphane,

1
@Stphane Un commento in ritardo, ma usare un interruttore in questa situazione va contro il principio del minimo stupore. Un'istruzione switch dovrebbe controllare la selezione dei dati, non controllare il flusso del programma.
FWDekker,

« Switch confronta un'espressione con valori diversi ed esegue uno specifico blocco di codice a seconda del valore a cui è uguale l'espressione.» Quindi ogni blocco può valutare espressioni sussidiarie che a loro volta possono indicare al flusso di esecuzione di restituire o saltare alcune istruzioni ... Non credo che il passaggio andrebbe contro il principio del minimo stupore in questo caso molto ristretto ma, detto questo, il contesto originale e i requisiti possono effettivamente richiedere alcuni refactoring.
Stphane,

4
$a = 1;

switch($a) {

  case "1":

    if  ($condition1){
      break;
    }

    if  ($condition2){
      break;
    }

    if  ($condition3){
      break;
    }
}

In questo modo ho ottenuto quello che volevo. Uso un interruttore ha solo un caso definito e quindi uso break in case per scegliere se la condizione. Il motivo per cui uso l'interruzione: condizione1 e condizione2 possono entrambi soddisfare, in quella situazione viene applicata solo condizione1 .IF è selettivo in base all'ordine.


8
Non hai bisogno di variabili per questo. Basta usareswitch(true) { case true:
Maxim Krizhanovsky il

1

No.

Ma che ne dici di:

$a="test";
if("test"==$a)
{
  if ($someOtherCondition)
  {
    echo "yes";
  }
}
echo "finish";

3
Grazie, ma sto cercando una versione più semplice per evitare troppe ifdichiarazioni
Muhammad Usman,

2
@Usman: se hai più condizioni, devi verificarle. Il controllo di una condizione implica tradizionalmente una ifdichiarazione. Non sono sicuro di come ti aspetti di evitarlo.
Oliver Charlesworth,

1

Basta spostare il codice che non dovrebbe essere eseguito sul else/elseiframo. Non vedo davvero perché vorresti fare quello che stai cercando di fare.


1

La semplice risposta è che no, non c'è modo di interrompere ifun'istruzione senza interrompere completamente l'esecuzione (tramite exit). Altre soluzioni non funzioneranno per me perché non riesco a cambiare la struttura ifdell'istruzione, poiché sto iniettando codice in un plugin, in questo modo:

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

0

Rispondere alla tua domanda se ciò è realizzabile o meno, quindi sì che è realizzabile utilizzando l'operatore "goto" di php.

Ma dal punto di vista etico, non è una buona pratica usare "goto" e non c'è bisogno di usare goto, quindi questo significa che il codice deve essere ricostruito in modo tale che il requisito di goto possa essere rimosso.

In base al codice di esempio che hai pubblicato sopra, si può vedere chiaramente che il codice può essere ricostruito e che il codice non più richiesto può essere eliminato o commentato (se esiste la possibilità di utilizzarlo in futuro).


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

combinando le tue affermazioni, penso che questo ti darebbe il risultato desiderato. pulito e semplice, senza avere troppe dichiarazioni.

per il codice brutto e bello, la mia raccomandazione sarebbe:

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

da qualche parte nel tuo codice normale

myfunction();

0

Penso che tu stia cercando questo:

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

    // go ahead , all is fine
}

Il manuale di php mostra degli foresempi, ma penso che funzioni anche perif


-1

ho una soluzione semplice senza molte modifiche. la dichiarazione iniziale è

Voglio rompere l'istruzione if sopra e interrompere l'esecuzione dell'eco "yes"; o tali codici che non sono più necessari per essere eseguiti, potrebbe esserci o meno una condizione aggiuntiva, esiste un modo per farlo?

quindi sembra semplice. prova il codice in questo modo.

$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";

se vuoi provare senza questo codice, è semplice. e puoi tornare quando vuoi. un'altra soluzione è i blocchi di commenti. o semplicemente pensando e prova in un altro codice separato e copia incolla solo il risultato nel tuo codice finale. e se un codice non è più necessario, nel tuo caso, il risultato può essere

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

con questo codice, la dichiarazione originale è completamente rispettata .. :) e più leggibile!


-2

La soluzione semplice è commentarla.

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

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

Il vantaggio aggiuntivo è che non stai modificando il codice originale e puoi datarlo, iniziarlo e spiegarne il motivo.

Perché il voto negativo, secondo la richiesta del PO, penso che questa sia una soluzione perfettamente valida.

"Voglio [rompere l'istruzione if sopra e] interrompere l'esecuzione dell'eco" yes "; o quei codici che non sono più necessari per essere eseguiti, potrebbe esserci o meno una condizione aggiuntiva, c'è modo di farlo?"

In effetti qualcuno potrebbe guardare alcune delle altre soluzioni, un anno dopo e chiedersi cosa sta succedendo lì. Secondo il mio suggerimento, si potrebbe lasciare una buona documentazione per riferimento futuro, che è sempre una buona pratica.


2
Questo non risolve il problema. La pausa potrebbe anche essere in un if.
Jimmy T.

Non puoi commentare in un'istruzione if? O commentarne uno? Intendi usare un if per escludere l'esecuzione? In tal caso, qual è il punto della rottura allora, non è che cosa se le dichiarazioni sono per? Commentalo anche tu. Scusa, ma non vedi il tuo punto.
Artistico

Qualcosa del genere: a: if ("test" == $ a) {... if (...) break a; ...}
Jimmy T.

-3

Che dire dell'utilizzo dell'operatore ternario?

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

Che è identico a questa istruzione if / else:

<?php
 if (empty($_POST['action'])) {
   $action = 'default';
 } else {
   $action = $_POST['action'];
 }
?>

In PHP7:$a = $_POST['action'] ?? 'default';
Tobias Mühl,

-3

Per interrompere completamente l'esecuzione del resto dello script, puoi semplicemente farlo

Uscita; // Al posto della pausa. Il resto del codice non verrà eseguito


-4

Sono in ritardo alla festa ma volevo contribuire. Sono sorpreso che nessuno abbia suggerito exit(). È buono per i test. Lo uso sempre e funziona come un incantesimo.

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

Il codice si fermerà alle exit()e tutto ciò che non verrà eseguito dopo.

Risultato

Clark Kent is Superman

Funziona con foreach()e while()pure. Funziona ovunque lo metti davvero.

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

echo "finish";

Risultato

nothing gets printed here.

Usalo con a forloop()

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

Risultato

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

In uno scenario normale

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

Risultato

Make hot chocolate great again!

-7
$a="test";
if("test"!=$a)
{
echo "yes";                   
}
 else
 {
  echo "finish";
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.