Alguma maneira de quebrar se declaração em PHP?

129

Existe algum comando no PHP para parar de executar a ifinstrução atual ou pai , igual breakou break(1)para switch/ loop. Por exemplo

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

echo "finish";

no código acima, o PHP não funcionará echo "test";e irá paraecho "finish";

Eu preciso disso para 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";

Quero breaka ifdeclaração acima e paro de executar echo "yes";ou esses códigos que não são mais necessários para serem executados, pode haver ou não uma condição adicional, existe maneira de fazer isso?

Atualização: Apenas 2 anos depois de postar essa pergunta, eu cresci, aprendi como o código pode ser escrito em pequenos pedaços, por que os if's aninhados podem parecer um cheiro de código e como evitar esses problemas em primeiro lugar, escrevendo pequenas funções gerenciáveis.

Muhammad Usman
fonte
15
Nenhum dos seus exemplos faz sentido logicamente.
precisa saber é o seguinte
1
@ Usuário: Se não houver uma condição, o echo(no seu exemplo) nunca será executado. Então você também pode excluí-lo.
Oliver Charlesworth
2
Não é try catchuma opção?
Giannis christofakis
Primeiro, pensei que Tim era apenas rude ... Mas depois pensei que ele estava certo ... Por que você teria algum código por trás de uma quebra incondicional? Depurando? Eu gosto de sair de loops com continue; E seria bom interromper consultas muito difíceis com o comando "basta parar aqui" ...if (condition) { if ( oneothercondition ) stop; if ( yetothercondition ) stop; // go ahead , all is fine }
Joeri 29/04
@ Joeri, não sei as idéias iniciais de Muhhamad por que ele precisava de uma pausa; Mas no meu caso agora é para fins de depuração, certo. Em alguns casos, isso economizaria tempo. Nos casos em que não é possível adicionar pontos de interrupção '(quando não estiver usando um IDE e / ou tiver que trabalhar em um site ao vivo por alguns motivos, etc.)
Viktor Borítás

Respostas:

216

Não se preocupe com os comentários de outros usuários, eu entendo você, às vezes é necessário desenvolver essas coisas "sofisticadas" . Se conseguirmos quebrar um if, muitos ifs aninhados não serão necessários, tornando o código muito mais limpo e estético.

Este código de exemplo ilustra que CERTAS SITUAÇÕES onde foram violadas podem ser muito mais adequadas do que muitos ifs aninhados feios ... se você não tiver enfrentado essa determinada situação, não significa que ela não existe .

Código feio

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

}

Código bonito

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

Como @NiematojakTomasz diz, o uso de gotoé uma alternativa, o ruim disso é que você sempre precisa definir o rótulo (ponto de destino).

AgelessEssence
fonte
29
Ótimo! Às vezes, as perguntas são mal compreendidas devido ao seu profundo senso. Você entendeu perfeitamente, eu preciso de um código limpo para evitar rastreamento finalif
Muhammad Usman
4
Eu precisava executar o mesmo código após cada teste bem-sucedido (cerca de 3 ou 4 testes) e colocar um elseifem cada teste com falha. Era exatamente isso que eu estava procurando, agora meu código é compatível com KISS e DRY :) Obrigado!
S3v3n
3
Cara isso parece sujo! Mas fica o meu upvote .. Eu estou trabalhando em um sistema sujo;)
LeonardChallis
8
@rdlowrey, conversa é livre, então por favor, mostre-nos um exemplo de "OOP Bem escrito" para resolver questão OP: 3
AgelessEssence
7
Não confunda a solicitação da amostra para ataques pessoais ... na verdade, você está perdendo algo importante, nem toda a codificação deve ser OOP, é uma loucura escrever tarefas simples com a mágica * da OOP.
AgelessEssence
98

Encapsule seu código em uma função. Você pode parar de executar uma função returna qualquer momento.

Maxim Krizhanovsky
fonte
2
Eu pensei que você queria um if, não uma função? ;)
Arnaud Le Blanc
3
@ arnaud576875 se o código estiver em uma função, você poderá usar return na instrução if para interromper a execução.
Maxim Krizhanovsky
1
Uma função deve ter "1 entrada" e "1 saída". RETORNOS Múltiplos são desleixados e propensos a erros.
Old Walter Walter
@ OldManWalter Isso é verdade apenas para retornar dados reais. No entanto, o tratamento de erros é uma exceção comum a esta regra. Uma exceção de lançamento ou retorno falso em vários locais é perfeitamente aceitável sem atingir as armadilhas comuns que a mentalidade "uma entrada e uma saída" está tentando se proteger.
Danielson317
41

maneira adequada de fazer isso:

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

Depois de ler alguns dos comentários, percebi que o tratamento de exceções nem sempre faz sentido para o controle de fluxo normal. Para um fluxo de controle normal, é melhor usar "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();
}

Você também pode salvar os valores de retorno do processo nas variáveis ​​e depois verificar os blocos de falha / exceção cujo processo falhou.

Rahul Ranjan
fonte
1
Exceções podem ser úteis nesses casos, mas parece que você as utiliza incorretamente. As exceções são excepcionais, não para o fluxo normal do programa. Se a falha for excepcional, o process_x-z deve lançar a exceção por si só; clean_all_processes () seria melhor em um bloco finalmente, pois é a limpeza que deve ser feita de qualquer maneira.
Jimmy T.
Eu melhorei a solução.
Rahul Ranjan
Razão pela qual eu não uso, finalmente, é, não é suportado até php5.5
Rahul Ranjan
20

Porque você pode quebrar fora de um do / while loop, vamos " fazer " uma rodada. Com um tempo (falso) no final, a condição nunca é verdadeira e não se repetirá novamente.

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
fonte
Ninguém diz que você deve usar isso. É apenas um exemplo para "sair".
Markus Zeller
2
Abordagem arrumada - faz o trabalho.
18719 benjaminhull
16

Goto :

O operador goto pode ser usado para pular para outra seção do programa. O ponto de destino é especificado por um rótulo seguido de dois pontos, e a instrução é fornecida como goto seguida pelo rótulo de destino desejado. Este não é um goto irrestrito completo . O rótulo de destino deve estar no mesmo arquivo e contexto, o que significa que você não pode pular de uma função ou método, nem pular para um. Você também não pode pular para qualquer tipo de estrutura de loop ou switch. Você pode pular fora deles, e um uso comum é usar um goto no lugar de uma pausa em vários níveis ...

NiematojakTomasz
fonte
82
Toda vez que você usa goto, o bebê Jesus come um gatinho. Além disso, xkcd.com/292
12
Desculpe por ser consistente. Eu referenciei a página de manual do php explicando o uso exato da palavra-chave mencionada. E mesmo que seja uma solução suja, ainda é a solução correta.
NiematojakTomasz
3
Não entendo exatamente como não é uma boa prática fazer isso. É muito mais simples do que todas as outras soluções?
538ROMEO
1
Acordou com Sébastien. Em alguns casos, o operador goto é muito útil e simples.
28416 Jerry
6
Não se preocupe, os programadores sempre farão você sentir que não está codificando corretamente e deseja que codifiquemos como eles. Isso é ainda mais verdadeiro na comunidade php, porque somos um monte de codificadores hipster e o PHP nos dá essas palavras-chave da liberdade e a liberdade de julgarmos como todos fazem as coisas. Eu usei (não extensivamente) a gotopalavra - chave nos códigos de produção e nunca tive problemas.
precisa saber é o seguinte
7

Existe um comando: goto

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


}



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

No entanto, lembre- gotose de não ser uma prática recomendada, pois faz com que o código seja formatado de maneira incomum.

T.Todua
fonte
1
Eu testei esse script, o código abaixo para ir para Area1; não será executado.
Leon Armstrong
6

Você pode usar um do-while (false):

    <?php
    do if ($foo)
    {
      // Do something first...

      // Shall we continue with this block, or exit now?
      if ($abort_if_block) break;

      // Continue doing something...

    } while (false);
    ?>

conforme descrito em http://php.net/manual/en/control-structures.if.php#90073

UltraDEVV
fonte
5

Não, não há como "quebrar" um bloco if como você faria dentro de loops. :(
Então transforme seu teste em um switch!

Eu me pergunto por que ninguém o incentivou a usar a instrução switch desde (mesmo que você não tenha muitos casos de teste).
Você acha que é muito detalhado?

Eu definitivamente aceitaria isso aqui

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

Para mim, as exceções são destinadas a gerar erros e não a realmente controlar falhas de execução.
Se o comportamento de interrupção que você está tentando definir não é sobre erros inesperados, o tratamento de exceções não é a solução certa aqui :/.

Stphane
fonte
Idéia interessante, mas eu não a usaria para código "real".
7284 Jimmy T.
1
"real", o que você quer dizer? :/
Stphane
1
@ Stphane Um comentário tardio, mas usar uma opção nessa situação vai contra o princípio de menos espanto. Uma instrução switch deve controlar a seleção de dados, não controlar o fluxo do programa.
FWDekker
« Switch compara uma expressão com valores diferentes e executa um bloco de código específico, dependendo de qual valor a expressão é igual a.» Então, cada bloco pode avaliar expressões subsidiárias que, por sua vez, podem instruir o fluxo de execução a retornar ou ignorar algumas instruções ... Eu não acho que a opção seja contrária ao princípio de menor espanto neste caso de uso muito restrito, mas, dito isso, o contexto original e os requisitos podem de fato exigir alguma refatoração.
Stphane
4
$a = 1;

switch($a) {

  case "1":

    if  ($condition1){
      break;
    }

    if  ($condition2){
      break;
    }

    if  ($condition3){
      break;
    }
}

Dessa maneira, consegui o que queria. Eu uso um switch apenas com um caso definido e, em seguida, uso break-case para escolher se a condição. A razão pela qual eu uso a quebra: condição1 e condição2 pode satisfazer, nessa situação, apenas a condição1 é aplicada .IF é seletivo de acordo com a ordem.

user3530437
fonte
8
Você não precisa de variável para isso. Basta usarswitch(true) { case true:
Maxim Krizhanovsky
1

Não.

Mas que tal:

$a="test";
if("test"==$a)
{
  if ($someOtherCondition)
  {
    echo "yes";
  }
}
echo "finish";
Oliver Charlesworth
fonte
3
Obrigado, mas estou procurando uma versão mais simples para evitar muitas ifdeclarações
Muhammad Usman
2
@ Usuário: Se você tiver várias condições, precisará verificar. A verificação de uma condição tradicionalmente envolve uma ifdeclaração. Não tenho certeza de como você espera evitar isso.
Oliver Charlesworth
1

Basta mover o código que não deve ser executado para else/elseiframificar. Realmente não vejo por que você gostaria de fazer o que está tentando fazer.

Mchl
fonte
1

A resposta simples é que não, não há como interromper uma ifdeclaração sem interromper completamente a execução (via exit). Outras soluções não funcionarão para mim porque não posso alterar a estrutura da ifinstrução, pois estou injetando código em um plug-in, assim:

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
fonte
0

Respondendo à sua pergunta se isso é possível ou não, então sim, é possível usando o operador "goto" do php.

Mas, eticamente, não é uma boa prática usar "goto" e, como é necessário usar goto, isso significa que o código precisa ser reconstruído para que o requisito de goto possa ser removido.

De acordo com o código de exemplo que você postou acima, pode-se ver claramente que o código pode ser reconstruído e o código que não é mais necessário pode ser excluído ou comentado (se houver possibilidade de uso no futuro).

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

combinando suas declarações, acho que isso lhe daria o resultado desejado. limpo e simples, sem ter muitas declarações.

para o código feio e bonito, minha recomendação seria:

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

em algum lugar do seu código normal

myfunction();
Arthur Kielbasa
fonte
0

Eu acho que você está procurando por isso:

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

    // go ahead , all is fine
}

O manual php mostra forexemplos, mas acho que também funciona paraif

Joeri
fonte
-1

Eu tenho uma solução simples, sem muitas mudanças. a declaração inicial é

Eu quero quebrar a instrução if acima e parar de executar o eco "yes"; ou tais códigos que não são mais necessários para serem executados, pode haver ou não uma condição adicional, existe uma maneira de fazer isso?

então, parece simples. tente código como este.

$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 você quiser experimentar sem esse código, é simples. e você pode voltar quando quiser. outra solução são blocos de comentários. ou simplesmente pensando e tente outro código separado e copie e cole apenas o resultado no seu código final. e se um código não for mais necessário, no seu caso, o resultado poderá ser

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

com este código, a declaração original é completamente respeitada .. :) e mais legível!

christian audebert
fonte
-2

A solução simples é comentar.

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

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

O benefício adicional é não alterar o código original e você pode datar, inicializá-lo e apresentar um motivo.

Por que o voto negativo, de acordo com a solicitação do OP, acho que essa é uma solução perfeitamente válida.

"Eu quero [quebrar a instrução if acima] e parar de executar o eco" yes "; ou esses códigos que não são mais necessários para serem executados, pode haver ou não uma condição adicional, existe alguma maneira de fazer isso?"

De fato, alguém poderia olhar para algumas das outras soluções, um ano depois, e se perguntar o que está acontecendo lá. Conforme minha sugestão, pode-se deixar uma boa documentação para referência futura, o que é sempre uma boa prática.

ArtisticPhoenix
fonte
2
Isso não resolve o problema. O intervalo também pode estar em um if.
7274 Jimmy T.
Você não pode comentar em uma declaração if? Ou comente um? Você quer dizer usar um if para excluir a execução? Em caso afirmativo, qual é o objetivo da pausa, não é para isso que servem as declarações? Apenas comente isso também. Desculpe, mas não entendo o seu ponto.
ArtisticPhoenix
Algo assim: a: ​​if ("test" == $ a) {... if (...) quebra a; ...}
Jimmy T.
-3

Que tal usar o operador ternário?

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

O que é idêntico a esta declaração if / else:

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

Para parar completamente o restante do script, você pode simplesmente fazer

Saída; // No lugar do intervalo. O restante do código não será executado

Mark Kasina
fonte
-4

Estou atrasado para a festa, mas queria contribuir. Estou surpreso que ninguém tenha sugerido exit(). É bom para testar. Eu uso o tempo todo e funciona como charme.

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

O código irá parar em exit()e tudo depois não será executado.

Resultado

Clark Kent is Superman

Funciona com foreach()e while()também. Funciona em qualquer lugar onde você realmente coloca.

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

echo "finish";

Resultado

nothing gets printed here.

Use-o com um forloop()

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

Resultado

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

Em um cenário de caso normal

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

Resultado

Make hot chocolate great again!
Balloon Fight
fonte
-7
$a="test";
if("test"!=$a)
{
echo "yes";                   
}
 else
 {
  echo "finish";
}
Shanon
fonte