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


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


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.


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.


@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


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

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



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


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


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


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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.