Будь-який спосіб зламати, якщо заява в 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 роки після опублікування цього питання я виріс, я дізнався, як код можна писати невеликими шматками, чому вкладений, якщо може бути запах коду, і як уникнути таких проблем в першу чергу, написавши керовані невеликі функції.


15
Жоден із ваших прикладів логічно не має сенсу.
Тім Піцкер

1
@Usman: Якщо немає умови, то echo(у вашому прикладі) ніколи не буде виконано. Таким чином, ви можете також видалити його.
Олівер Чарлсворт,

2
Чи не try catchваріант?
giannis christofakis

Спершу я подумав, що Тім просто грубий ... Але потім я подумав, що він правильний ... Чому б ти мав якийсь код за безумовною перервою? Налагодження? Мені подобається прориватися для циклів з продовженням; І було б непогано розбити дуже складні запити командою "просто зупинись тут" ...if (condition) { if ( oneothercondition ) stop; if ( yetothercondition ) stop; // go ahead , all is fine }
Joeri

@ Джорі, я не знаю початкових ідей Мухаммада, чому йому потрібна перерва; Але в моєму випадку зараз це налагодження, правда. У деяких випадках це заощадить час. У випадках, коли не вдається додати точки перерви '(коли не використовується IDE та / або доведеться працювати з
активного

Відповіді:


216

Не хвилюйтесь щодо коментарів інших користувачів, я можу вас зрозуміти, СОТРІБНИЦТВО, коли розробляєте ці "химерні" речі . Якщо ми можемо зламати if, багато вкладених ifs не знадобиться, що робить код набагато більш чистим та естетичним.

Цей зразок коду ілюструє, що НАРОДНІ СИТУАЦІЇ, де порушені, якщо можуть бути набагато придатнішими, ніж багато потворних вкладених ifs ... якщо ви не стикалися з певною ситуацією, це не означає, що її немає .

Некрасивий код

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
Людина це відчуває себе брудно! Але це отримує мою нагоду .. Я працюю над брудною системою;)
LeonardChallis

8
@rdlowrey, розмова безкоштовна, тому БУДЬ ласка, покажіть нам приклад "Добре написаного OOP", щоб вирішити питання про ОП: 3
AgelessEssence

7
Не плутайте запит вибірки з особистими атаками ... насправді вам не вистачає чогось важливого, не все кодування повинно бути OOP, це божевільна річ, що пише прості завдання з магією * OOP.
AgelessEssence

98

Інкапсулюйте свій код у функції. Ви можете returnбудь-коли припинити виконання функції .


2
Я хоч ти хотів, якщо не функція? ;)
Арно Ле Блан

3
@ arnaud576875, якщо код є функцією, тоді ви можете використовувати return в операторі if, щоб перервати виконання.
Максим Крижановський

1
Функція повинна мати "1 вихід" та "1 вихід". Кілька RETURNS неохайний і схильний до помилок.
Старий Вальтер

@OldManWalter Це справедливо лише для повернення фактичних даних. Однак поводження з помилками є загальним винятком із цього правила. Виняток викидання або повернення помилкового в декількох місцях цілком прийнятні, не зачіпаючи загальні підводні камені, менталітет "намагається захистити".
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
Винятки можуть бути корисними в цих випадках, але, здається, ви неправильно їх використовуєте. Винятки є винятковими, не для нормальної програми. Якщо помилка є винятковою, процес_x-z повинен викинути виняток сам по собі; Очистити_all_process () було б краще в остаточному блоці, оскільки це очищення, що все одно потрібно зробити.
Джиммі Т.

Я вдосконалив рішення.
Рахул Ранджан

Причина, яку я нарешті не використовував, це не підтримується до php5.5
Рахул

20

Оскільки ви можете вирватися з циклу do / while, давайте « зробимо » один раунд. З часом (помилковим) в кінці, умова ніколи не відповідає дійсності і не повториться.

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

Ніхто не каже, що ви повинні користуватися цим. Це лише приклад, щоб «вирватися».
Маркус Зеллер

2
Охайний підхід - робить роботу.
Бенджамінхул

16

goto :

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


82
Кожного разу, коли ви користуєтесь goto, немовля Ісус їсть кошеня. Також xkcd.com/292

12
Вибачте за послідовність. Я посилався на сторінку керівництва php, що пояснює точне використання згаданого ключового слова. І навіть якщо це брудне рішення, це все-таки правильне рішення.
NiematojakTomasz

3
Я точно не розумію, як це не дуже добре робити? Це набагато простіше, ніж усі інші рішення?
538ROMEO

1
Домовились із Себастьєном. У деяких випадках оператор goto дуже корисний і простий.
Джеррі

6
Не хвилюйтесь, програмісти завжди будуть відчувати, що ви не кодуєте належним чином, і хочете, щоб ми кодували їх як. Це ще більше вірно в PHP-спільноті, оскільки ми є купою хіпстерських кодерів, і PHP дає нам ці ключові слова свободи і свободу бути настільки суворою щодо того, як все робить. Я використовував (не широко) gotoключове слово у виробничих кодах, і ніколи не мав проблем.
вдегенне

7

Існує команда: goto

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


}



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

Однак пам’ятати gotoне є рекомендованою практикою, оскільки це змушує код форматувати незвично.


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


5

Ні, немає ніякого способу "зламати" блок if, як ти, всередині циклів. :(
Тож перетворіть свій тест на 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 Пізній коментар, але використання перемикача в цій ситуації суперечить принципу найменшого здивування. Очікується, що оператор перемикання контролюватиме вибір даних, а не контроль потоку програми.
FWDekker

« Перемикач порівнює вираз із різними значеннями та виконує певний блок коду залежно від того, якому значенню вираз дорівнює.» Тоді кожен блок може оцінювати допоміжні вирази, які, в свою чергу, можуть доручити потоку виконання повернути або пропустити деякі вказівки ... Я не думаю, що перемикач не піде проти принципу найменшого здивування в цій дуже звуженій скриньці, але, сказано, вихідний контекст і вимоги дійсно можуть вимагати певного рефакторингу.
Стфан

4
$a = 1;

switch($a) {

  case "1":

    if  ($condition1){
      break;
    }

    if  ($condition2){
      break;
    }

    if  ($condition3){
      break;
    }
}

Таким чином я отримав те, що хочу. Я використовую перемикач має лише певний випадок, а потім використовую перерву на випадок, щоб вибрати, якщо умова. Причина, чому я використовую перерву: умова1 та умова2 можуть задовольняти, в цій ситуації застосовується лише умова1.


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 вище і припинити виконувати відлуння "так"; або такі коди, які більше не потрібно виконувати, можуть бути або не можуть бути додатковою умовою, чи це можливо зробити?

так, здається простим. спробуйте такий код.

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

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

Чому голосування проти, відповідно до прохання ОП, я вважаю, що це цілком правильне рішення.

"Я хочу [порушити оператор if вище та] припинити виконання ехо" так "; або такі коди, які більше не потрібно виконувати, можуть бути або не можуть бути додатковою умовою, чи є спосіб це зробити?"

Насправді хтось міг поглянути на якісь інші рішення, через рік і поцікавитися, що там відбувається. Згідно з моєю пропозицією, можна було б залишити гарну документацію для подальшого ознайомлення, що завжди є хорошою практикою.


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'];
?>

Що ідентично цьому, якщо / 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.

Використовуйте його з a 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.