Любой способ сломать оператор if в PHP?


129

Есть ли какая-либо команда в PHP, чтобы остановить выполнение текущего или родительского ifоператора, так же, как breakили break(1)для switch/ loop. Например

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

echo "finish";

в приведенном выше коде PHP не echo "test";подходит и перейдет вecho "finish";

Мне это нужно, если

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

Я хочу, чтобы breakуказанное ifвыше утверждение прекратило выполнение echo "yes";или такие коды, которые больше не нужны для выполнения, может быть или не быть дополнительным условием, есть ли способ сделать это?

Обновление: всего через 2 года после публикации этого вопроса я вырос, я узнал, как код можно писать небольшими кусками, почему вложенные if могут быть запахом кода и как избежать таких проблем в первую очередь, написав управляемые небольшие функции.


15
Ни один из ваших примеров не имеет логического смысла.
Тим Пицкер

1
@Usman: Если нет условия, то echo(в вашем примере) никогда не будет выполнен. Так что вы можете удалить его.
Оливер Чарльзуорт,

2
Не try catchвариант?
Яннис Кристофакис 01

Сначала я подумал, что Тим был просто груб ... Но потом я подумал, что он прав ... Зачем вам какой-то код за безусловным разрывом? Отладка? Мне нравится выходить из цикла for с помощью continue; И было бы неплохо разбить очень сложные вопросы с помощью команды «просто остановись здесь» ...if (condition) { if ( oneothercondition ) stop; if ( yetothercondition ) stop; // go ahead , all is fine }
Джоэри

@Joeri, я не знаю первоначальных идей Муххамада, зачем ему нужен перерыв; Но в моем случае теперь это цели отладки, верно. В некоторых случаях это сэкономит время. В случаях, когда невозможно добавить точки останова (когда не используется IDE и / или по каким-то причинам приходится работать на действующем сайте и т. Д.)
Виктор Боритас

Ответы:


216

Не беспокойтесь о комментариях других пользователей, я вас понимаю, ИНОГДА при разработке это "навороченное" дело . Если мы сможем разорвать if, много вложенных if не понадобится, что сделает код более чистым и эстетичным.

Этот пример кода показывает, что ОПРЕДЕЛЕННЫЕ СИТУАЦИИ, в которых нарушено если, могут быть гораздо более подходящими, чем множество уродливых вложенных if ... если вы не сталкивались с этой определенной ситуацией, это не значит, что ее не существует .

Уродливый код

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

}

Красивый код

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

Как говорит @NiematojakTomasz, использование gotoявляется альтернативой, и плохо в том, что вам всегда нужно определять метку (точечную цель).


29
Большой! Иногда вопросы понимают неправильно из-за их глубокого смысла. У вас все отлично, мне нужен чистый код, чтобы не отслеживать конецif
Мухаммад Усман

4
Мне нужно было выполнять один и тот же код после каждого успешного теста (примерно 3 или 4 теста) и ставить один и тот же код elseifна каждый неудачный тест. Это именно то, что я искал, теперь мой код совместим с KISS и DRY :) Спасибо!
s3v3n

3
Чувак, это грязно! Но он получает мои положительные голоса .. Я работаю над грязной системой;)
Леонард Чаллис,

8
@rdlowrey, разговор бесплатный, ПОЖАЛУЙСТА, покажите нам пример «Хорошо написанного ООП», чтобы решить вопрос ОП: 3
AgelessEssence

7
Не путайте запрос образца с личными атаками ... на самом деле, вы упускаете что-то важное, не все кодирование должно быть ООП, это безумие, писать простые задачи с помощью магии * ООП.
AgelessEssence

98

Инкапсулируйте свой код в функции. Вы можете прекратить выполнение функции с помощью return.


2
Я думал, вам нужно если, а не функцию? ;)
Арно Ле Блан

3
@ arnaud576875, если код находится в функции, вы можете использовать return в операторе if, чтобы прервать выполнение.
Максим Крижановский

1
Функция должна иметь «1 вход» и «1 выход». Множественные ВОЗВРАТЫ небрежны и подвержены ошибкам.
Старик Уолтер

@OldManWalter Это верно только для возврата фактических данных. Однако обработка ошибок - частое исключение из этого правила. Исключение выброса или возврат false в нескольких местах вполне приемлемы, не затрагивая распространенные ошибки, от которых пытается защититься менталитет «1 путь внутрь, 1 выход».
danielson317

41

правильный способ сделать это:

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

Прочитав некоторые комментарии, я понял, что обработка исключений не всегда имеет смысл для нормального управления потоком. Для нормального потока управления лучше использовать «Если еще»:

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

Вы также можете сохранить возвращаемые значения процесса в переменных, а затем проверить в блоках ошибок / исключений, какой процесс завершился ошибкой.


1
В этих случаях могут быть полезны исключения, но кажется, что вы ими злоупотребляете. Исключения бывают исключительными, не для нормального выполнения программы. Если сбой является исключительным, то process_x-z должен сам сгенерировать исключение; clean_all_processes () было бы лучше в finally-блоке, поскольку это очистка, которую необходимо выполнить в любом случае.
Джимми Т.

Я улучшил решение.
Рахул Ранджан

Причина, по которой я, наконец, не использовал, это то, что он не поддерживается до php5.5
Рахул Ранджан

20

Поскольку вы можете выйти из цикла do / while, позвольте нам « выполнить » один раунд. Если в конце указано while (false) , условие никогда не будет истинным и больше не повторится.

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

2
Аккуратный подход - свое дело делает.
benjaminhull

16

goto :

Оператор goto можно использовать для перехода к другому разделу программы. Целевая точка указывается меткой, за которой следует двоеточие, а инструкция дается как goto, за которой следует желаемая целевая метка. Это не полный неограниченный переход . Целевая метка должна находиться в том же файле и контексте, что означает, что вы не можете ни выйти из функции или метода, ни перейти к одному из них. Вы также не можете перейти в какую-либо структуру цикла или переключателя. Вы можете выпрыгнуть из них, и обычно используется goto вместо многоуровневого разрыва ...


82
Каждый раз, когда вы используете goto, Младенец Иисус ест котенка. Также xkcd.com/292

12
Извините за последовательность. Я сослался на страницу руководства php, объясняющую точное использование упомянутого ключевого слова. И даже если это грязный раствор, это все равно правильное решение.
NiematojakTomasz

3
Я не совсем понимаю, почему это не очень хорошая практика? Это намного проще, чем все другие решения?
538ROMEO

1
Согласен с Себастьяном. В некоторых случаях оператор goto очень полезен и прост.
Джерри

6
Не волнуйтесь, программисты всегда будут давать вам понять, что вы неправильно пишете и хотите, чтобы мы писали так же, как они. Это еще более верно для сообщества php, потому что мы группа хипстерских программистов, а PHP дает нам эти ключевые слова свободы и свободу осуждать то, как все делают что-то. Я использовал (нечасто) gotoключевое слово в производственных кодах, и у меня никогда не было проблем.
vdegenne

7

Есть команда: goto

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


}



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

Однако помните, что gotoэто не рекомендуется, потому что это приводит к необычному форматированию кода.


1
Я тестировал этот сценарий, код ниже goto Area1; не будет выполнен.
Леон Армстронг


5

Нет, нет способа «сломать» блок if, как внутри циклов. :(
Так что превратите свой тест в switch!

Интересно, почему никто не рекомендовал вам использовать оператор switch с тех пор (даже если у вас не было много тестовых примеров),
вы думаете, что это слишком многословно?

Я бы определенно пошел на это здесь

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

Для меня исключения предназначены для того, чтобы вызывать ошибки, а не для контроля ошибок выполнения.
Если поведение разрыва, которое вы пытаетесь установить, не связано с неожиданной ошибкой (-ями), обработка исключений здесь не является правильным решением :/.


Интересная идея, но я бы не стал использовать ее для «настоящего» кода.
Джимми Т.

1
"настоящий", что ты имеешь в виду? :/
Stphane

1
@Stphane Поздний комментарий, но использование переключателя в этой ситуации противоречит принципу наименьшего удивления. Предполагается, что оператор switch будет управлять выбором данных, а не потоком выполнения программы.
FWDekker

« Switch сравнивает выражение с разными значениями и выполняет определенный блок кода в зависимости от того, какому значению соответствует выражение.» Затем каждый блок может оценивать вспомогательные выражения, которые, в свою очередь, могут указывать потоку выполнения возвращать или пропускать некоторые инструкции ... Я не думаю, что переключатель будет противоречить принципу наименьшего удивления в этом очень узком сценарии использования, но, при этом, исходный контекст и требования действительно могут потребовать некоторого рефакторинга.
Stphane

4
$a = 1;

switch($a) {

  case "1":

    if  ($condition1){
      break;
    }

    if  ($condition2){
      break;
    }

    if  ($condition3){
      break;
    }
}

Таким образом я получил то, что хочу. Я использую переключатель только для определенного случая, а затем использую break, чтобы выбрать условие if. Причина, по которой я использую break: и условие1, и условие2 могут удовлетворять, в этой ситуации применяется только условие1. IF выбирается в соответствии с порядком.


8
Для этого вам не нужна переменная. Просто используйтеswitch(true) { case true:
Максим Крижановский

1

Нет.

Но как насчет:

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

3
Спасибо, но я ищу более простую версию этого, чтобы избежать лишних ifзаявлений
Мухаммад Усман

2
@Usman: Если у вас несколько условий, вам нужно их проверить. Проверка условия традиционно включает в себя ifутверждение. Не знаю, как этого избежать.
Оливер Чарльзуорт,

1

Просто переместите код, который не должен выполняться, в else/elseifветвь. Я действительно не понимаю, зачем вам делать то, что вы пытаетесь сделать.


1

Простой ответ заключается в том, что нет способа прервать выполнение ifоператора без полной остановки выполнения (через exit). Другие решения для меня не подойдут, потому что я не могу изменить структуру ifоператора, так как я вставляю код в плагин, например:

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

Отвечая на ваш вопрос, достижимо это или нет, тогда да, это достижимо с использованием оператора "goto" в php.

Но с этической точки зрения использование «goto» не является хорошей практикой, и если нет необходимости использовать goto, это означает, что код необходимо реконструировать таким образом, чтобы требование goto могло быть удалено.

В соответствии с образцом кода, который вы разместили выше, ясно видно, что код можно реконструировать, а код, который больше не требуется, можно либо удалить, либо прокомментировать (если есть возможность использовать в будущем).


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

объединяя ваши утверждения, я думаю, что это даст вам желаемый результат. чистый и простой, без лишних заявлений.

Для уродливого и красивого кода я бы рекомендовал:

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

где-то в вашем нормальном коде

myfunction();

0

Думаю, вы это ищете:

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

    // go ahead , all is fine
}

В руководстве по php показаны forпримеры, но я думаю, что он также работает дляif


-1

у меня есть простое решение без особых изменений. исходное заявление

Я хочу прервать выполнение приведенного выше оператора if и прекратить выполнение echo "yes"; или таких кодов, которые больше не нужно выполнять, может быть или не быть дополнительных условий, есть ли способ сделать это?

так что вроде просто. попробуйте такой код.

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

если вы хотите попробовать без этого кода, это просто. и вы можете вернуться, когда захотите. другое решение - блоки комментариев. или просто подумайте и попробуйте другой отдельный код и скопируйте и вставьте только результат в окончательный код. и если код больше не нужен, в вашем случае результат может быть

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

с этим кодом исходное утверждение полностью соблюдается .. :) и более читабельно!


-2

Простое решение - закомментировать это.

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

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

Дополнительным преимуществом является то, что вы не меняете исходный код, и вы можете датировать его, инициализировать и указать причину.

Почему голосование против, согласно запросу OP, я думаю, что это совершенно правильное решение.

«Я хочу [нарушить оператор if выше и] прекратить выполнение echo« yes »; или такие коды, которые больше не нужно выполнять, могут быть или не могут быть дополнительными условиями, есть ли способ сделать это?»

Фактически, кто-то мог бы посмотреть на некоторые другие решения год спустя и задаться вопросом, что там происходит. Согласно моему предложению, можно оставить хорошую документацию для использования в будущем, что всегда является хорошей практикой.


2
Это не решает проблемы. Перерыв также может быть в случае, если.
Джимми Т.

Вы не можете прокомментировать оператор if? Или закомментировать? Вы имеете в виду использование if, чтобы исключить выполнение? Если да, то в чем смысл перерыва, разве не для этого нужны операторы «а что, если»? Просто прокомментируйте это тоже. Извините, но не понимаю вашей точки зрения.
ArtisticPhoenix

Примерно так: a: if ("test" == $ a) {... if (...) break a; ...}
Джимми Т.

-3

А как насчет использования тернарного оператора?

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

Что идентично этому оператору if / else:

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

На PHP7:$a = $_POST['action'] ?? 'default';
Тобиас Мюль

-3

Чтобы полностью остановить выполнение остальной части скрипта, вы можете просто сделать

выход; // Вместо разрыва. Остальной код не будет выполняться


-4

Я опоздал на вечеринку, но хотел внести свой вклад. Я удивлен, что никто не предложил exit(). Это хорошо для тестирования. Я использую его постоянно и работает как шарм.

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

Код остановится на, exit()и все, что будет дальше, не запустится.

результат

Clark Kent is Superman

Он также работает с foreach()и while(). Он работает везде, где вы его действительно разместите.

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

echo "finish";

результат

nothing gets printed here.

Используйте его с forloop()

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

результат

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

В обычном случае

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

результат

Make hot chocolate great again!

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.