Carcleo 4 Denunciar post Postado Maio 15, 2012 Bom dia pessoal. Estive lendo sobre a Estrutura Try Catch e, pelo que notei, ela serve para substituir de forma mais profissional e elegante as exibições de erros que, normalmente, são geradas pela condicional IF. Estou certo? Ou seja: Ou se usa IF ou Try Catch. É isso mesmo? Tipo try { } Catch { } Ou If { } else { ] É isso mesmo? Se for isso, o meu código abaixo esta uma bagunça: <?php if(isset($_GET["acao"]) and $_GET["acao"]=="cadastra") { try{ $select_admin_string="select usuario_admin from admin where usuario_admin = '".$_POST['cad_usuario_admin']."'"; $select_admin = $conexao->query($select_admin_string); if($select_admin->num_rows==0) { $cadastro_admin_string=" insert into admin (nome_admin, usuario_admin, senha_admin, bloqueio_admin) values( '".$_POST['cad_nome_admin']."', '".$_POST['cad_usuario_admin']."', '".$_POST['cad_senha_admin']."', 'n' ) "; $cadastro_admin = $conexao->query($cadastro_admin_string); if($cadastro_admin) { echo "<table align=\"center\" width=\"600px\" height=\"300px\"><tr><td align=\"center\" valign=\"middle\">"; echo "Cadastro Efetuado com sucesso"; echo "<br />"; echo "Redirecionando em 10 segundos..."; echo "</td></tr></table>"; header("refresh: 10; url=admin_cad.php"); } else { echo "<table align=\"center\" width=\"600px\" height=\"600px\"><tr><td align=\"center\" valign=\"middle\">"; echo "Erro no cadastro. Tente novament!"; echo "<br />"; echo "Redirecionando em 10 segundos..."; echo "</td></tr></table>"; header("refresh: 10; url=admin_cad.php"); } } else { echo "<table align=\"center\" width=\"600px\" height=\"300px\"><tr><td align=\"center\" valign=\"middle\">"; echo "Este usuário já esta cadastrado, por favor escolha outro"; echo "<br />"; echo "Redirecionando em 10 segundos..."; echo "</td></tr></table>"; header("refresh: 10; url=admin_cad.php"); } }catch(Exception $e) { echo $e->getMessage(); } } ?> Compartilhar este post Link para o post Compartilhar em outros sites
Guilherme_90 33 Denunciar post Postado Maio 15, 2012 Não vejo neste sentido. Pelo que entendo, o Try é para tratamento de erros. Apesar que no if/else você PODE fazer, porém ele é uma condicional para fazer algum teste da lógica de seu sistema, é diferente do Try/Catch onde você teste se vai acontecer algum erro. Eu disse que pode fazer tratamento de erro no if, porém eu acho isso uma "gambiarra", dependendo da situação, até por que não é em todo lugar que vai ficar usando try/catch. Posso esar errado, alguém mais experiênte ajuda? Compartilhar este post Link para o post Compartilhar em outros sites
Vinicius Rangel 208 Denunciar post Postado Maio 15, 2012 você não consegue tratar um erro com if else você faria o que? if($erro == "ERRO, you have a sintaxe error"){ echo 'Esses dados não podem ser acessados'; } o if else são condições como nosso amigo disse para ajudar na lógica mais não para tratar erro. o try eu vou tentar explicar bem lógico try em inglês é tentar bom ele vai tentar fazer algo o catch é se não der certo ai você vai lançar uma mensagem pro usuário evitando que mostre erros como: erro de sintaxe, variavel não definida etc... Compartilhar este post Link para o post Compartilhar em outros sites
Carcleo 4 Denunciar post Postado Maio 15, 2012 Entendi. Vou vere o que mudar aqui e reposto como ficou Compartilhar este post Link para o post Compartilhar em outros sites
Henrique Barcelos 290 Denunciar post Postado Maio 15, 2012 Primeiramente você precisa entender o conceito de exceção. ex.ce.ção, [Datação: século XVI] 1. ato ou efeito de excetuar 2. o que não se submete à regra 3. desvio da regra geral (comum) 4. privilégio Uma exceção é algo anormal que acontece em seu sistema. Anormal deve ser entendido como "não é esperado que isso ocorra sempre". As exceções em linguagens de programação surgiram da necessidade de possibilitar o tratamento de erros antes que estes chegassem ao usuário através de mensagens na tela. Esse tipo de controle era feito antigamente com blocos if ... else, entretanto, algo acabava se perdendo. Também não era possível postergar o tratamento desse erro para uma camada superior (o que dizem ser desaconselhável, mas muitas vezes, é necessário). Além disso, uma exceção traz algumas informações agregadas, tal como o código, a linha, o arquivo e uma pilha de execução. É importante que em um bloco try ... catch haja apenas o código crítico, sujeito a erros, e algumas dependências, não o código todo. Além disso, você precisa estar ciente de que TODO o código posterior à chamada que gerou a exceção não será executado. Nesse ponto, os blocos diferem. Por exempo: Imagine que você precisa executar 2 funções, tal que a segunda depende da primeira. Com if ... else: condicao = algumafuncao(); if(condicao é válida) then facaalgo(); else trateoerro(); endif; outrafuncao(); // será executado mesmo que a chamada de "algumafuncao" falhe Com o bloco try... catch: try algumafuncao(); // lança uma exceção facaalgo(); // Nada a partir daqui será executado outrafuncao(); catch excecao trateoerro(); Aí você fala: - Ah, eu poderia mover a chamada de outrafuncao para dentro do bloco if. Nesse caso, pode, mas e se fossem 3 funções que dependessem uma da outra? Tente fazer com if ... else, se você conseguir fazer essa dependência sem criar um outro bloco if ... else eu mudo de nome. Com try ... catch eu mantenho essa dependência linearmente: try funcao1(); funcao2(); funcao3(); catch excecao trataroerro(); Se 1 lançar exceção, nem 2 nem 3 são executadas. Se 2 lançar, 3 não é executada e assim por diante. Compartilhar este post Link para o post Compartilhar em outros sites
Guilherme_90 33 Denunciar post Postado Maio 15, 2012 você não consegue tratar um erro com if else Acredito que sim, veja: <? if(error()){ die(); } ?> Apesar de que, o die() vai parar o script, caso entre nesta condicional. Se eu tiver errado me corrija, quero entender melhor! :thumbsup: Compartilhar este post Link para o post Compartilhar em outros sites
Prog 183 Denunciar post Postado Maio 15, 2012 O if pode até funcionar para erros do PHP/sistema, mas para erros lançados pelo usuário será bem mais fácil/adequado trabalhar com try...catch. Compartilhar este post Link para o post Compartilhar em outros sites
Vinicius Rangel 208 Denunciar post Postado Maio 15, 2012 você consegue esconder os erros com o @ frente as funções.. lembrando que o @ só pode ser usado somente em expressões. até onde meus mínimos conhecimentos me permitem com o if else não é possível tratar o erro de fato, mais eu posso ter me equivocado no comentário sim. o que melhor quis dizer é que tratar um erro de fato com if else não é possível pois ele vai trabalhar como você fez algo se retorna tal valor ele vai mostrar uma mensagem. já o try catch ele vai ler todas as ações por exemplo uma inserção de dados depois que ele ler tudo se não tiver nenhum erro ele continua se não o catch lança uma nova exceção. Compartilhar este post Link para o post Compartilhar em outros sites
Luis Paullo 47 Denunciar post Postado Maio 15, 2012 Bom usa os 2 em conjuto e melhor ainda kkkk trabalhando com try cacth e throw!! fica algo assim! if (!isset($this->var)) throw new ErrorException('Houve um erro na execução. Tente novamente'); no inicializador do sua aplicação! try { //init da aplicação } catch (Exception $erro) { echo json_encode(array('msg' => $erro->getMessage(), 'response' => false)); $this->logError($erro->getMessage()); } todo throw é lançado pro bloco try ! torna muito facil faze um log de erros dessa forma! em uma aplicação seguindo MVC por exemplo (bootstrap), você tem so 1 bloco try catch pra todo o sistema, apenas recebendo os throw's! Compartilhar este post Link para o post Compartilhar em outros sites
Guilherme_90 33 Denunciar post Postado Maio 15, 2012 você consegue esconder os erros com o @ frente as funções.. Isso PRA mim se chamada gambiarra. Só pra brincar, fui obrigado a criar essa funçãozinha! kkkk <? function getGambiarra($string){ $getArroba = substr($string, 0); $i = 0; while($getArroba[0] == '@'): echo 'Seu pog! ' , PHP_EOL; $i++; if($i == 10): exit; endif; endwhile; } ?> Compartilhar este post Link para o post Compartilhar em outros sites
Vinicius Rangel 208 Denunciar post Postado Maio 15, 2012 Isso PRA mim se chamada gambiarra, #@?$%~ gambiarra. siim, uahuhauhauhahuahuuhaa. gambiarra total do mesmo modo que é tratar os erros com if else Compartilhar este post Link para o post Compartilhar em outros sites
Evandro Oliveira 331 Denunciar post Postado Maio 15, 2012 Try-Catch trabalha sem interferir no fluxo. Dizer que é "mais profissional" ou que é "um substituto ao IF" são equívocos. Cada um tem seu lugar e ocasião corretas para uso. Um bloco IF-ELSE está presente no fluxo do programa, faz parte do seu algoritmo, uma exceção, como o próprio nome já diz é reservada para algo imprevisto. Ainda, o lançamento de uma exceção - quase sempre - consiste em uma verificação prévia através de IF. O tratamento de erros é melhor operado com try-catch, como já mencionado pelo Henrique, devido à pilha de execução. Quando trabalhamos com funções, sempre conhecemos seu retorno. Se isso não é verdadeiro, há um problema de arquitetura do sistema. Uma vez que o retorno é conhecido, precisamos de um escape para comportamentos inesperados: FUNÇÃO: DIVISÃO ( NÚMERO: DIVIDENDO, NÚMERO: DIVISOR ) -> NÚMERO: QUOCIENTE Temos que, uma função, chamada divisão recebe dois argumentos: - Um numeral, chamado dividendo - Um numeral, chamado divisor E retorna um numeral. Porém, como todos sabemos, a divisão possui uma exceção: quando o divisor é zero. A primeira solução que poderíamos tomar é alterar o formato de retorno da função para devolver um mapa, oferecendo um identificador de erros e/ou o resultado: FUNÇÃO: DIVISÃO ( NÚMERO: DIVIDENDO, NÚMERO: DIVISOR ) -> LISTA: [ INTEIRO: COD_ERRO, NÚMERO: QUOCIENTE ] Percebe que, seguindo este raciocínio, TODAS as funções existentes no planeta </hipérbole> deveriam oferecer esse tipo de retorno? Com algum raciocínio, observamos que esse comportamento é, obviamente, incorreto. Deve haver alguma outra forma da função lançar erros. FUNÇÃO: DIVISÃO ( NÚMERO: DIVIDENDO, NÚMERO: DIVISOR ) -> NÚMERO: QUOCIENTE SE DIVISOR NÃO É 0 ENTÃO RETORNE DIVIDENDO / DIVISOR LANCE ERRO "NÃO É POSSÍVEL DIVIDIR POR ZERO!" FIM FUNÇÃO Para interromper o fluxo e impedir que falhas posteriores consequentes desta aconteçam, seria necessário lançar um erro fatal. Qualquer outro erro que prossiga com o fluxo acarretará em erros em série NÚMERO: QUANTIDADE_ATUAL = 50 NÚMERO: QUANTIDADE_TOTAL = 0 NÚMERO: PERCENTAGEM = DIVISÃO ( QUANTIDADE_ATUAL, QUANTIDADE_TOTAL ) * 100 // Erro: Multiplicação de NULO por 100 Observamos que esta também não é a técnica mais adequada para tratamento de erros. Catch oferece uma alternativa para pegar - a tradução literal de "catch" - e retornar ao fluxo atual ou, em casos mais extremos, sair do fluxo de forma elegante. FUNÇÃO: DIVISÃO ( NÚMERO: DIVIDENDO, NÚMERO: DIVISOR ) -> NÚMERO: QUOCIENTE SE DIVISOR É 0 ENTÃO LANCE EXCEÇÃO: DIVISÃO_POR_ZERO RETORNE DIVIDENDO / DIVISOR FIM FUNÇÃO A primeira diferença que notamos é: na primeira abordagem poderíamos ter como retorno um NÚMERO ou um NULO. Na segunda abordagem, sempre que houver um retorno ele será do tipo esperado. Dessa forma não encadeamos erros e, de quebra, ganhamos um manipulador para impedir erros consequentes: NÚMERO: QUANTIDADE_ATUAL = 50 NÚMERO: QUANTIDADE_TOTAL = 0 TENTATIVA: NÚMERO: PERCENTAGEM = DIVISÃO ( QUANTIDADE_ATUAL, QUANTIDADE_TOTAL ) * 100 EXCETO DIVISÃO_POR_ZERO: NÚMERO: PERCENTAGEM = 0 FIM TENTATIVA Na maioria das linguagens, há ainda outra vantagem: Manipulação por tipo de exceção FUNÇÃO: DIVISÃO ( VARIÁVEL: DIVIDENDO, VARIÁVEL: DIVISOR ) -> NÚMERO: QUOCIENTE SE (TIPO(DIVIDENDO) = NUMERAL) E (TIPO(DIVISOR) = NUMERAL) É FALSO ENTÃO LANCE EXCEÇÃO: ARGUMENTO_INVÁLIDO SE DIVISOR É 0 ENTÃO LANCE EXCEÇÃO: DIVISÃO_POR_ZERO RETORNE DIVIDENDO / DIVISOR FIM FUNÇÃO VARIÁVEL: QUANTIDADE_ATUAL = [ENTRADA_DO_USUÁRIO] VARIÁVEL: QUANTIDADE_TOTAL = [ENTRADA_DO_USUÁRIO] TENTATIVA: NÚMERO: PERCENTAGEM = DIVISÃO ( QUANTIDADE_ATUAL, QUANTIDADE_TOTAL ) * 100 EXCETO ARGUMENTO_INVÁLIDO: IMPRIMA "POR FAVOR, INFORME DOIS NÚMEROS" PARE EXCETO DIVISÃO_POR_ZERO: NÚMERO: PERCENTAGEM = 0 FIM TENTATIVA Como bem observado pelo Henrique, há ainda a possibilidade de empilhar tentativas e, conforme o tipo de exceção, tratar no local adequado, fugindo apenas do fluxo que será impossível atender: FUNÇÃO: DIVISÃO ( VARIÁVEL: DIVIDENDO, VARIÁVEL: DIVISOR ) -> NÚMERO: QUOCIENTE SE (TIPO(DIVIDENDO) = NUMERAL) E (TIPO(DIVISOR) = NUMERAL) É FALSO ENTÃO LANCE EXCEÇÃO: ARGUMENTO_INVÁLIDO SE DIVISOR É 0 ENTÃO LANCE EXCEÇÃO: DIVISÃO_POR_ZERO RETORNE DIVIDENDO / DIVISOR FIM FUNÇÃO TENTATIVA: VARIÁVEL: QUANTIDADE_ATUAL = [ENTRADA_DO_USUÁRIO] VARIÁVEL: QUANTIDADE_TOTAL = [ENTRADA_DO_USUÁRIO] TENTATIVA: NÚMERO: PERCENTAGEM = DIVISÃO ( QUANTIDADE_ATUAL, QUANTIDADE_TOTAL ) * 100 EXCETO DIVISÃO_POR_ZERO: NÚMERO: PERCENTAGEM = 0 FIM TENTATIVA EXCETO ARGUMENTO_INVÁLIDO: IMPRIMA "POR FAVOR, INFORME DOIS NÚMEROS" PARE FIM TENTATIVA Observe que no último exemplo, como não será possível continuar sem definir o valor de PERCENTAGEM, o tratamento dessa exceção fica um nível acima do escopo onde a variável é necessária. Compartilhar este post Link para o post Compartilhar em outros sites
Henrique Barcelos 290 Denunciar post Postado Maio 15, 2012 @Evandro Oliveira, show!!! :clap: Compartilhar este post Link para o post Compartilhar em outros sites
Bruno Augusto 417 Denunciar post Postado Maio 15, 2012 É importante que em um bloco try ... catch haja apenas o código crítico, sujeito a erros, e algumas dependências, não o código todo. Além disso, você precisa estar ciente de que TODO o código posterior à chamada que gerou a exceção não será executado. Do primeiro ponto eu discordo e o segundo eu questiono. Discordo porque eu entendo que todo o código o qual dependa do "código crítico" deve sim ser executado dentro do bloco try e o motivo vêm explicado no porquê de eu questionar. Eu questiono, a segunda afirmação no caso, porque todo ódigo posterior a chamada que gerou a Exception não será executado se a dita Exception não tiver sido pèga. Se ela o tiver, será sim executado: try { throw new Exception( 'Message Here' ); } catch( Exception $e ) { echo $e -> getMessage(); } echo '<br /><br />Hello World!'; Esse fragmento mostra na tela ambas as mensagens porque como a Exception foi pêga, pela ausência de um exit/die no bloco catch, o fluxo continua. Agora se apenas o "código crítico" for executado dentro do bloco try, teremos testes, deixando, assim, de confiar na nossa aplicação. Imagine que o "código crítico" seja um método de classe ou função que possa disparar uma Exception antes de retornar alguma coisa. Se disparou antes de retornar, NULL é assumido. $name = NULL; // Evita um Undefined variable try { $name = name(); } catch( Exception $e ) { echo $e -> getMessage(); } function name() { throw new Exception( 'Message Here' ); } if( ! is_null( $name ) ) { printf( '<br /><br />Hello %s!', $name ); } Não sei vocês, mas eu não gosto desse tipo de coisa. Muito melhor seria: try { printf( '<br /><br />Hello %s!', name() ); } catch( Exception $e ) { echo $e -> getMessage(); } function name() { throw new Exception( 'Message Here' ); } Claro que nesse exemplo NUNCA será exibida a mensagem, já que a dummy function ali não faz nada mais do que disparar a Exception. Compartilhar este post Link para o post Compartilhar em outros sites
Henrique Barcelos 290 Denunciar post Postado Maio 15, 2012 Acho que me fiz entender mal. O que eu quis dizer foi invés de fazer: try { // trocentas linhas de código // trecho crítico // código dependente da execução do trecho crítico } catch( Exception $e ) { echo $e -> getMessage(); } Fazer: // trocentas linhas - 1 try { // trecho crítico, que pode lançar uma exceção // código dependente da execução do trecho crítico } catch( Exception $e ) { echo $e -> getMessage(); } Por que isso? Na minha humilde opinião torna o código mais legível. Ponto. Em questões de performance, não muda nada... Compartilhar este post Link para o post Compartilhar em outros sites
Bruno Augusto 417 Denunciar post Postado Maio 15, 2012 Ah bom, então assim, sim! :P Resumindo, até antes de a primeira linha, do primeiro código, que possa disparar a primeira Exception, fora do bloco try. A partir daí, dentro dele. :thumbsup: Eu tenho uma pergunta esse respeito. Os frameworks diversos que vemos por aí afora usam Exceptions para QUALQUER tipo de erro que eles não possam consertar na hora (como um cast forçado). Isso não cabe no conceito de uma Exception, cabe? É apenas uma forma "Orientada a Objetos" (bem entre aspas) para um trigger_error(). E aí? Compartilhar este post Link para o post Compartilhar em outros sites
Henrique Barcelos 290 Denunciar post Postado Maio 16, 2012 Isso não cabe no conceito de uma Exception, cabe? É apenas uma forma "Orientada a Objetos" (bem entre aspas) para um trigger_error(). E aí? Depende muito... É uma característica do PHP, por ser dinamicamente tipada, você não consegue garantir um tipo para o parâmetro sempre. Se você espera um parâmetro de um certo tipo e tenta garantir isso através de um casting, então o normal é a função/método em questão receber um parâmetro daquele tipo. Quando o parâmetro é de outro tipo, constitui-se uma exceção à regra de tipo, então, por essa visão, cabe uma exceção. Em Java, por exemplo, não existem "erros" em runtime, só exceções. Se você avaliar que o objetivo de uma aplicação é funcionar corretamente, quando algo dá errado, você tem uma exceção à regra do "deve funcionar". Compartilhar este post Link para o post Compartilhar em outros sites