O bloco Try / Catch no PHP não captura a exceção

97

Estou tentando executar este Exemplo # 1 desta página: http://php.net/manual/en/idioma.exceptions.php

<?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    return 1/$x;
}
try {
    echo inverse(5) . "\n";
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}
// Continue execution
echo "Hello World\n";
?>

No entanto, em vez da saída desejada, recebo:

0.2
Fatal error: Uncaught exception 'Exception' with message 'Division by zero.' 
in xxx:
7 Stack trace: #0 xxx(14): inverse(0) #1 {main} thrown in xxx on line 7

O ambiente de desenvolvedor que estou usando está UniServer 3.5comPHP 5.2.3

Krassi
fonte
1
Você pode nos mostrar seu código? O único erro que você pode cometer para obter esse erro é capturar a exceção errada (ou nenhuma).
Tammo
2
O código é EXATAMENTE idêntico (acabei de adicionar novas linhas) ... de qualquer forma, copiei o código mais uma vez em um arquivo de teste e aqui está a mesma mensagem de erro: 0.2 Erro fatal: exceção não detectada 'Exceção' com mensagem 'Divisão por zero . ' em W: \ www \ test.php: 4 Rastreamento de pilha: # 0 W: \ www \ test.php (11): inverse (0) # 1 {main} lançado em W: \ www \ test.php na linha 4 Eu realmente não tenho ideia do que está acontecendo lá ... talvez configuração do PHP com defeito?
Krassi
1
Algumas versões de extensão mais antigas causaram problemas com o tratamento de exceções. 5.2.3 é antigo e um bug pode estar por trás do erro. Você pode atualizar o PHP? O UniServer 3.5 também é bastante antigo, considerando que a versão de produção atual é 5.5. 3.5 é um erro de digitação?
outis
1
Olhando as informações de lançamento do UniServer ( wiki.uniformserver.com/index.php/… ), 3.5 aparentemente não é um erro de digitação. Atualize para UniServer 5.5 e tente o código de amostra novamente.
outis
1
outis, obrigado pela dica :). Isso é o que eu fazia naquela época - mudei para o XAMPP (não gosto da nova versão do UniServer). 3.5 não é um erro de digitação, mas o servidor funcionou perfeitamente para mim, então nunca me preocupei em atualizá-lo.
Krassi,

Respostas:

217

Eu simplesmente tive esse problema exato em que parecia que eu tinha até copiado o nome da exceção e ainda assim não o pegou. Acontece que foi um erro estúpido, mas achei que deveria postar meu caso aqui caso haja outra pessoa na mesma situação.

Eu tive a minha exceção em meu namespace chamado A eo script estava em um namespace chamado B . O problema era que eu tinha A \ MyException que é igual (em PHP) \ B \ A \ MyException (porque meu script está no namespace chamado B !). Tudo que tive que fazer para consertar foi adicionar barra invertida (ou o que quer que seja chamado) ao nome da exceção para que ficasse assim: \ A \ MyException

Pijusn
fonte
7
muito obrigado por postar isso porque eu teria ficado vários dias sem perceber meu erro.
tipu
79
Isso resolveu meu problema, um bloco de captura simples preguiçoso em código com namespace deveria ser catch (\Exception $e). Sem a barra invertida Exceptioné específico para o namespace e não será correspondido (ou capturado).
joemaller de
3
Obrigado por postar isso!
keepkimi de
2
Obrigado por postar isso, acabei de passar as últimas horas enlouquecendo por que meu bloqueio de captura não estava funcionando. Palma da face principal.
Mitch
4
Felicidades! Salvei meu dia (e neurônios ...) :)
vegetal
67

Uma pergunta bem velha, ainda ...

Eu também tive esse problema (e foi assim que encontrei este post), mas apenas uma simples experiência me permitiu encontrar a solução. Tente mudar Exceptionpara \Exception. Funcionou para mim!

EDITAR:

Como sivann apontou nos comentários, o uso de namespace deve fazer a mesma coisa. Então, simplesmente coloque use \Exception as Exception;antes de sua declaração de classe.

Enethion
fonte
Brilhante! :) Provavelmente levaria horas para descobrir, só não pensei em namespacing. Obrigado!
Alexander Gilmanov
Sim! também: "use \ Exception como Exception;" no topo faz a mesma coisa.
sivann,
@ sii-anik Tente usar o namespace exatamente como escreveu sivann.
Enethion
apenas use Exception;deve fazê-lo
Diego Ponciano
Obrigado! @Enethion
Noamway
32

Tente colocar em catch(\Exception $e)vez de catch(Exception $e). Se você estiver usando um código que não conhece muito bem, ou - especialmente - se estiver usando um framework, ele pode substituir a exceção PHP padrão por uma própria e, portanto, você pode ir para o caminho errado e obter o resultado indesejado. Se você acabou de colocar \Exception, tem certeza de que está capturando a exceção básica do PHP.

Vladimir Despotovic
fonte
@crassi, você experimentou minha sugestão?
Vladimir Despotovic
2
isso funcionou para mim
cljk
20

Você não pode usar os blocos típicos try {} catch {} em PHP como faria em outra linguagem como C # (Csharp).

Se você fizer isto:

try{
    //division by zero
    $number = 5/0;
}
catch(Exception $ex){
    echo 'Got it!';
}

Você não verá a mensagem 'Entendi!' mensagem nunca. Por quê? É porque o PHP sempre precisa que uma exceção seja "lançada". Você precisa definir seu próprio manipulador de erros e lançar uma exceção com ele.

Veja a função set_error_handler : http://php.net/manual/es/function.set-error-handler.php

Rowinson Gallego
fonte
6
Não é a mesma coisa;) Você precisava lançar uma exceção sozinho, e foi o que eu disse (<< É só porque o PHP sempre precisa que uma exceção seja "lançada" >>) @JaredFarrish
Rowinson Gallego
Sim, mas como não é o mesmo?
Jared Farrish
Esse link está morto, mas achei útil: w3schools.com/php/func_error_set_error_handler.asp
Loathing
No PHP Versão 7.3.9, $number = 5/0;não gera uma exceção. $numberestá definido para ser INF.
virtualmic
6

Minha inicial, porém, é que você tem um erro de digitação no nome da exceção que está capturando / lançando, mas se o seu código for exatamente o mesmo, não tenho certeza do que exatamente está acontecendo.

Tente a seguinte modificação do script original e cole os resultados. Isso ajudará a diagnosticar seu problema um pouco melhor.

<?php

//set up exception handler to report what we didn't catch
function exception_handler($exception) {

    if($exception instanceof MyException) {
        echo "you didn't catch a myexception instance\n";

    } else if($exception instanceof Exception) {
        echo "you didn't catch a exception instance\n";

    } else {
        echo "uncaught exception of type: ".gettype($exception)."\n";
    }

    echo "Uncaught exception: " , $exception->getMessage(), "\n";
}

//install the handler
set_exception_handler('exception_handler');

class MyException extends Exception {
}

function inverse($x) {
    if (!$x) {
        throw new MyException('Division by zero.');
    }
    else return 1/$x;
}

try {
    echo inverse(5) . "\n";
    echo inverse(0) . "\n";
} catch (MyException $e) {
    echo 'Caught myexception: ',  $e->getMessage(), "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}

// Continue execution
echo 'Hello World';
?>
Sfrench
fonte
4

Eu tive o mesmo problema com as configurações a seguir,

PHP 5.2.14 (cli) (construído: 12 de agosto de 2010 17:32:30) Copyright (c) 1997-2010 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2010 Zend Technologies com eAccelerator v0.9.5. 1 , Copyright (c) 2004-2006 eAccelerator, por eAccelerator

A solução é desativar o eAccelerator ou atualizá-lo. Tentei ambos e as duas correções funcionaram. O bug é relatado aqui https://eaccelerator.net/ticket/242 (NB. Firefox reclama sobre seu certificado SSL).

Agora estou executando o try catch corretamente com as seguintes configurações,

PHP 5.2.4 (cli) (construído em: 16 de outubro de 2007 09:13:35) Copyright (c) 1997-2007 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies com eAccelerator v0.9.6. 1 , Copyright (c) 2004-2010 eAccelerator, por eAccelerator

Yawar
fonte
3

no Xdebug, há uma configuração:

xdebug.show_exception_trace = 1

Isso forçará o php a gerar exceções, mesmo em um bloco try catch. Transforme isso para0

user2950254
fonte
2
No meu caso, tive que desabilitar o módulo xdebug completamente (mudar xdebug.show_exception_trace não foi suficiente).
Thomas Sahlin
Obrigado por este lembrete. Fiquei completamente confuso por um tempo.
Brian Litzinger
3

Se você estiver usando o PHP 7, você pode precisar do Throwable em vez do Exception

user5528384
fonte
Este é um post bastante antigo. Dê uma olhada na data do tópico antes de decidir responder. Além disso, sua resposta não é realmente útil, pois é: - incompleta - sem explicação do motivo
monofone
1
A explicação é que o PHP7 usa Throwable em vez de Exception. Esta discussão foi a primeira que encontrei quando encontrei o problema e queria contribuir. Comentários como esses são motivos pelos quais Stack não é amigável à comunidade.
user5528384
1
não era minha intenção ofendê-lo. Esta postagem apareceu na fila de revisão "Primeiras postagens" e, em minha opinião, não foi útil postar uma resposta a uma pergunta bastante antiga. E no momento em que este artigo foi escrito, o Question Throwable nem havia sido inventado no mundo do PHP. Seria útil se você escrever em sua resposta que Throwable é a interface implementada por Exception (e Error) e, portanto, também pode ser detectada. Mas não é um suplemento a uma exceção.
monofone
1

TLDR; certifique-se de ter use Exception;no topo de ambos os arquivos php

Sr. Heelis
fonte
0

Eu também estou experimentando isso. Eu li o comentário de Rowinson Gallego que afirmava que a exceção deve ser lançada. Então, modifiquei meu código de:

try
{
  $number = 5/0; //or other exception
}
catch(Exception $e)
{
  throw $e;
}

para dentro :

try
{
  $number = 5/0; //or other exception
}
catch(Exception $e)
{
  throw new Exception($e->getMessage(),$e->getCode());
}

Funciona.

Fauzie Adriansyah
fonte