Jakikolwiek sposób na złamanie instrukcji if w PHP?

129

Czy w PHP jest jakieś polecenie zatrzymania wykonywania bieżącej lub nadrzędnej ifinstrukcji, tak samo jak breaklub break(1)dla switch/ loop. Na przykład

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

echo "finish";

w powyższym kodzie PHP nie zrobi echo "test";i przejdzie doecho "finish";

Potrzebuję tego, jeśli

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

Chcę breakna ifrachunku powyżej i przystanku wykonującego echo "yes";lub takich kodów, które nie są już konieczne do wykonania, nie może być lub nie być dodatkowy warunek, czy istnieje sposób, aby to zrobić?

Aktualizacja: Zaledwie 2 lata po wysłaniu tego pytania dorosłem, dowiedziałem się, jak kod można pisać w małych kawałkach, dlaczego zagnieżdżone if może być zapachem kodu i jak uniknąć takich problemów w pierwszej kolejności, pisząc łatwe w zarządzaniu, małe funkcje.

Muhammad Usman
źródło
15
Żaden z twoich przykładów nie ma logicznego sensu.
Tim Pietzcker,
1
@Usman: Jeśli nie ma warunku, echo(w twoim przykładzie) nigdy nie zostanie wykonany. Więc równie dobrze możesz go usunąć.
Oliver Charlesworth,
2
Nie ma try catchtakiej opcji?
giannis christofakis
Najpierw pomyślałem, że Tim jest po prostu niegrzeczny ... Ale potem pomyślałem, że ma rację ... Dlaczego miałbyś mieć jakiś kod za bezwarunkową przerwą? Debugowanie? Lubię wychodzić z pętli for z kontynuacją; I byłoby miło podzielić bardzo trudne zapytania za pomocą polecenia „po prostu zatrzymaj się tutaj” ...if (condition) { if ( oneothercondition ) stop; if ( yetothercondition ) stop; // go ahead , all is fine }
Joeri
@Joeri Nie znam pierwszych pomysłów Muhhamada, dlaczego potrzebował przerwy; Ale w moim przypadku teraz jest to debugowanie, prawda. W niektórych przypadkach pozwoliłoby to zaoszczędzić czas. W przypadkach, gdy nie można dodać punktów przerwania (gdy nie korzystasz z IDE i / lub musisz pracować na działającej stronie z jakichś powodów itp.)
Viktor Borítás

Odpowiedzi:

216

Nie martw się komentarzami innych użytkowników, rozumiem cię, CZASAMI przy tworzeniu tych „wymyślnych” rzeczy są wymagane . Jeśli uda nam się złamać if, wiele zagnieżdżonych ifów nie będzie potrzebnych, dzięki czemu kod będzie znacznie bardziej przejrzysty i estetyczny.

Ten przykładowy kod ilustruje, że NIEKTÓRE SYTUACJE zostały przerwane, jeśli mogą być znacznie bardziej odpowiednie niż wiele brzydkich zagnieżdżonych ifów ... jeśli nie spotkałeś się z tą sytuacją, nie oznacza to, że nie istnieje .

Brzydki kod

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

}

Dobrze wyglądający kod

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

Jak mówi @NiematojakTomasz, użycie gotojest alternatywą, złe w tym jest to, że zawsze musisz zdefiniować etykietę (cel punktowy).

AgelessEssence
źródło
29
Wspaniały! Czasami pytania są źle rozumiane ze względu na ich głęboki sens. Masz to doskonale, potrzebuję czystego kodu, aby uniknąć śledzenia. Koniecif
Muhammad Usman
4
Musiałem wykonać ten sam kod po każdym udanym teście (około 3 lub 4 testów) i umieścić elseifna każdym nieudanym teście. Dokładnie tego szukałem, teraz mój kod jest zgodny z KISS i DRY :) Dzięki!
s3v3n
3
Człowieku, to jest brudne! Ale dostaję moje poparcie ... Pracuję nad brudnym systemem;)
LeonardChallis
8
@rdlowrey, rozmowa jest bezpłatna, więc PROSZĘ pokazać nam przykład „Dobrze napisanego OOP”, aby rozwiązać pytanie OP: 3
AgelessEssence,
7
Nie myl żądania próbki z atakami osobistymi ... w rzeczywistości brakuje ci czegoś ważnego, nie całe kodowanie powinno być OOP, jest szaloną rzeczą pisanie prostych zadań z magią * OOP.
AgelessEssence
98

Hermetyzuj swój kod w funkcji. Możesz przerwać wykonywanie funkcji returnw dowolnym momencie.

Maxim Krizhanovsky
źródło
2
Pomyślałem, że chciałeś funkcji jeśli, a nie? ;)
Arnaud Le Blanc
3
@ arnaud576875, jeśli kod jest w funkcji, możesz użyć return w instrukcji if, aby przerwać wykonywanie.
Maxim Krizhanovsky
1
Funkcja powinna mieć „1 wejście” i „1 wyjście”. Funkcja Multiple RETURNS jest niedbała i podatna na błędy.
Old Man Walter
@OldManWalter Dotyczy to tylko zwracania rzeczywistych danych. Jednak obsługa błędów jest częstym wyjątkiem od tej reguły. Wyjątek rzucania lub zwracanie fałszu w wielu lokalizacjach są całkowicie dopuszczalne bez uderzania w typowe pułapki, przed którymi stara się chronić mentalność „1 wejście, 1 wyjście”.
danielson317
41

właściwy sposób:

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

Po przeczytaniu niektórych komentarzy zdałem sobie sprawę, że obsługa wyjątków nie zawsze ma sens w przypadku normalnej kontroli przepływu. W przypadku normalnego przepływu sterowania lepiej jest użyć opcji „Jeśli inaczej”:

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

Możesz również zapisać wartości zwracane przez proces w zmiennych, a następnie sprawdzić w blokach błędów / wyjątków, który proces się nie powiódł.

Rahul Ranjan
źródło
1
W takich przypadkach wyjątki mogą być przydatne, ale wydaje się, że używasz ich niewłaściwie. Wyjątki są wyjątkowe i nie dotyczą normalnego przebiegu programu. Jeśli niepowodzenie jest wyjątkowe, wówczas proces_x-z powinien sam zgłosić wyjątek; clean_all_processes () byłaby lepsza w last-block, ponieważ jest czyszczona, co i tak musi zostać wykonane.
Jimmy T.
Poprawiłem rozwiązanie.
Rahul Ranjan,
Powodem, którego w końcu nie użyłem, jest to, że nie jest obsługiwany do php5.5
Rahul Ranjan
20

Ponieważ można rozbić się o do / while, daj nam „ zrobić ” jedną rundę. Z chwilą (fałsz) na końcu warunek nigdy nie jest prawdziwy i nie powtórzy się ponownie.

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
źródło
Nikt nie mówi, że musisz tego używać. To tylko przykład do „ucieczki”.
Markus Zeller
2
Porządne podejście - spełnia swoje zadanie.
benjaminhull
16

goto :

Goto operator może być używany, aby przejść do innej sekcji w programie. Punkt docelowy jest określony etykietą, po której następuje dwukropek, a instrukcja jest podawana jako goto, po której następuje żądana etykieta docelowa. To nie jest pełna nieograniczony goto . Etykieta docelowa musi znajdować się w tym samym pliku i kontekście, co oznacza, że ​​nie można wyskoczyć z funkcji lub metody ani też do nich przejść. Nie można również wskoczyć do jakiejkolwiek struktury pętli lub przełącznika. Możesz z nich wyskoczyć, a częstym zastosowaniem jest użycie goto zamiast wielopoziomowej przerwy ...

NiematojakTomasz
źródło
82
Za każdym razem, gdy używasz goto, Dzieciątko Jezus zjada kotka. Ponadto xkcd.com/292
12
Przepraszamy za konsekwencję. Odwołałem się do strony podręcznika php wyjaśniającej dokładne użycie wspomnianego słowa kluczowego. I nawet jeśli jest to brudne rozwiązanie, nadal jest to poprawne rozwiązanie.
NiematojakTomasz
3
Nie do końca rozumiem, dlaczego robienie tego nie jest dobrą praktyką? To dużo prostsze niż wszystkie inne rozwiązania?
538ROMEO
1
Uzgodniono z Sébastienem. W niektórych przypadkach operator goto jest bardzo przydatny i prosty.
Jerry
6
Nie martw się, programiści zawsze sprawią, że poczujesz, że nie kodujesz poprawnie i chcesz, abyśmy kodowali tak jak oni. Jest to jeszcze bardziej prawdziwe w społeczności php, ponieważ jesteśmy grupą koderów hipster, a PHP daje nam te słowa kluczowe związane z wolnością i swobodą oceniania tego, jak każdy coś robi. Użyłem (niezbyt intensywnie) gotosłowa kluczowego w kodach produkcyjnych i nigdy nie miałem problemów.
vdegenne
7

Istnieje polecenie: goto

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


}



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

Należy jednak pamiętać, że gotonie jest to zalecana praktyka, ponieważ powoduje to niezwykłe formatowanie kodu.

T.Todua
źródło
1
Przetestowałem ten skrypt, poniższy kod goto Area1; nie zostanie wykonany.
Leon Armstrong
5

Nie, nie ma sposobu na „przerwanie” bloku if, tak jak w przypadku pętli. :(
Więc zamień swój test w switch!

Zastanawiam się, dlaczego nikt nie zachęcał Cię do używania instrukcji switch, skoro (nawet jeśli nie masz zbyt wielu przypadków testowych).
Czy uważasz, że jest ona zbyt szczegółowa?

Zdecydowanie wybrałbym to tutaj

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

Dla mnie Wyjątki mają na celu wywołanie błędów, a nie tak naprawdę kontrolowanie błędów wykonania.
Jeśli zachowanie przerwania, które próbujesz ustawić, nie dotyczy nieoczekiwanych błędów, obsługa wyjątków nie jest tutaj właściwym rozwiązaniem :/.

Stphane
źródło
Ciekawy pomysł, ale nie użyłbym go do „prawdziwego” kodu.
Jimmy T.
1
„prawdziwe”, co masz na myśli? :/
Stphane,
1
@Stphane Spóźniony komentarz, ale użycie przełącznika w tej sytuacji jest sprzeczne z zasadą najmniejszego zdziwienia. Oczekuje się, że instrukcja switch będzie sterować wyborem danych, a nie przepływem programu.
FWDekker
« Przełącznik porównuje wyrażenie z różnymi wartościami i wykonuje określony blok kodu w zależności od wartości wyrażenia.» Następnie każdy blok może oceniać wyrażenia pomocnicze, które z kolei mogą nakazać przepływowi wykonania powrót lub pominięcie niektórych instrukcji… Nie sądzę, że zmiana byłaby sprzeczna z zasadą najmniejszego zdziwienia w tym bardzo zawężonym przypadku, ale, to powiedziawszy, oryginalny kontekst i wymagania mogą rzeczywiście wymagać pewnych refaktoryzacji.
Stphane
4
$a = 1;

switch($a) {

  case "1":

    if  ($condition1){
      break;
    }

    if  ($condition2){
      break;
    }

    if  ($condition3){
      break;
    }
}

W ten sposób otrzymałem to, czego chcę. Używam przełącznika tylko z określonym przypadkiem, a następnie używam przerwy w przypadku, aby wybrać warunek. Powód, dla którego używam przerwania: warunek1 i warunek2 mogą spełniać oba warunki, w tej sytuacji stosowany jest tylko warunek 1 .IF jest selektywny zgodnie z kolejnością.

user3530437
źródło
8
Nie potrzebujesz do tego zmiennej. Po prostu użyjswitch(true) { case true:
Maxim Krizhanovsky
1

Nie.

Ale co powiesz na:

$a="test";
if("test"==$a)
{
  if ($someOtherCondition)
  {
    echo "yes";
  }
}
echo "finish";
Oliver Charlesworth
źródło
3
Dzięki, ale szukam prostszej wersji, aby uniknąć zbyt wielu ifstwierdzeń
Muhammad Usman
2
@Usman: Jeśli masz wiele warunków, musisz je sprawdzić. Sprawdzanie stanu tradycyjnie obejmuje ifstwierdzenie. Nie jestem pewien, jak zamierzasz tego uniknąć.
Oliver Charlesworth
1

Po prostu przenieś kod, który nie powinien być wykonywany, do else/elseifgałęzi. Naprawdę nie rozumiem, dlaczego miałbyś chcieć robić to, co próbujesz zrobić.

Mchl
źródło
1

Prosta odpowiedź jest taka, że ​​nie, nie ma sposobu, aby zerwać z ifinstrukcją bez całkowitego zatrzymania wykonywania (via exit). Inne rozwiązania nie zadziałają, ponieważ nie mogę zmienić struktury ifinstrukcji, ponieważ wstrzykuję kod do wtyczki, na przykład:

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
źródło
0

Odpowiadając na twoje pytanie, czy jest to osiągalne, czy nie, to tak, można to osiągnąć za pomocą operatora "goto" w php.

Jednak z etycznego punktu widzenia używanie „goto” nie jest dobrą praktyką i jeśli nie ma potrzeby używania goto, oznacza to, że kod musi zostać zrekonstruowany w taki sposób, aby można było usunąć wymóg goto.

Zgodnie z przykładowym kodem, który opublikowałeś powyżej, wyraźnie widać, że kod można zrekonstruować, a kod, który nie jest już potrzebny, można usunąć lub skomentować (jeśli istnieje taka możliwość do wykorzystania w przyszłości).

Sandeep Garg
źródło
0
$arr=array('test','go for it');
$a='test';
foreach($arr as $val){
  $output = 'test';
  if($val === $a) $output = "";
  echo $output;
}
echo "finish";

łącząc twoje stwierdzenia, myślę, że dałoby to pożądany rezultat. przejrzyste i proste, bez zbyt wielu stwierdzeń.

dla brzydkiego i dobrze wyglądającego kodu, moja rekomendacja byłaby następująca:

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

gdzieś w swoim normalnym kodzie

myfunction();
Arthur Kielbasa
źródło
0

Myślę, że szukasz tego:

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

    // go ahead , all is fine
}

Podręcznik php zawiera forprzykłady, ale myślę, że działa również w przypadkuif

Joeri
źródło
-1

mam proste rozwiązanie bez wielu zmian. początkowe stwierdzenie to

Chcę przerwać powyższą instrukcję if i przestać wykonywać echo „tak”; lub takie kody, które nie są już potrzebne do wykonania, może istnieć lub nie musi być dodatkowy warunek, czy jest na to sposób?

więc wydaje się to proste. wypróbuj taki kod.

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

jeśli chcesz spróbować bez tego kodu, jest to proste. i możesz wrócić, kiedy chcesz. innym rozwiązaniem są bloki komentarzy. lub po prostu pomyśl i spróbuj w innym oddzielnym kodzie i skopiuj, wklej tylko wynik do końcowego kodu. a jeśli kod nie jest już potrzebny, w twoim przypadku rezultat może być

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

z tym kodem oryginalne oświadczenie jest całkowicie przestrzegane ... :) i bardziej czytelne!

christian audebert
źródło
-2

Prostym rozwiązaniem jest zakomentowanie tego.

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

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

Dodatkową korzyścią jest to, że nie zmieniasz oryginalnego kodu i możesz go opatrzyć datą, parafować i podać powód.

Dlaczego głosowanie przeciw, zgodnie z wnioskiem PO, myślę, że jest to doskonale uzasadnione rozwiązanie.

„Chcę [przerwać powyższą instrukcję if i] przestać wykonywać echo„ tak ”; lub takie kody, które nie są już potrzebne do wykonania, może istnieć lub nie musi istnieć dodatkowy warunek, czy istnieje sposób, aby to zrobić?"

Właściwie ktoś mógłby przyjrzeć się innym rozwiązaniom, za rok później i zastanowić się, co się tam dzieje. Zgodnie z moją sugestią, można zostawić dobrą dokumentację na przyszłość, co jest zawsze dobrą praktyką.

ArtystycznyPhoenix
źródło
2
To nie rozwiązuje problemu. Przerwa może również nastąpić w przypadku, gdy.
Jimmy T.
Nie możesz komentować w oświadczeniu if? Albo skomentować jeden? Czy masz na myśli użycie if, aby wykluczyć wykonanie? Jeśli tak, to po co to przerwa, czy nie jest to po co są stwierdzenia? Po prostu to skomentuj. Przepraszamy, ale nie rozumiem.
ArtisticPhoenix
Coś takiego: a: if ("test" == $ a) {... if (...) break a; ...}
Jimmy T.
-3

A co z użyciem operatora trójargumentowego?

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

Która jest identyczna z instrukcją if / else:

<?php
 if (empty($_POST['action'])) {
   $action = 'default';
 } else {
   $action = $_POST['action'];
 }
?>
Martin Stone
źródło
W PHP7:$a = $_POST['action'] ?? 'default';
Tobias Mühl
-3

Aby całkowicie zatrzymać działanie reszty skryptu, możesz po prostu zrobić

wyjście; // W miejscu przerwy. Reszta kodu nie zostanie wykonana

mark kasina
źródło
-4

Spóźniłem się na imprezę, ale chciałem wnieść swój wkład. Dziwię się, że nikt nie zaproponował exit(). Jest dobry do testów. Używam go cały czas i działa jak urok.

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

Kod zatrzyma się exit()i wszystko, co nastąpi później, nie będzie działać.

Wynik

Clark Kent is Superman

Działa również z foreach()i while(). Działa naprawdę wszędzie, gdzie go umieścisz.

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

echo "finish";

Wynik

nothing gets printed here.

Użyj go z forloop()

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

Wynik

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

W normalnym przypadku

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

Wynik

Make hot chocolate great again!
Walka balonowa
źródło
-7
$a="test";
if("test"!=$a)
{
echo "yes";                   
}
 else
 {
  echo "finish";
}
Shanon
źródło