Блок try / Catch в PHP не улавливает исключение

98

Я пытаюсь запустить этот пример №1 с этой страницы: http://php.net/manual/en/language.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";
?>

Однако вместо желаемого результата я получаю:

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

Я использую среду разработчика UniServer 3.5сPHP 5.2.3

Краси
источник
1
Вы можете показать нам свой код? Единственная ошибка, которую вы можете сделать, чтобы получить эту ошибку, - это перехват неправильного исключения (или нулевого).
Tammo
2
Код ТОЧНО идентичен (я только что добавил несколько символов новой строки) ... в любом случае, я скопировал код еще раз в тестовый файл, и вот то же сообщение об ошибке: 0.2 Неустранимая ошибка: неперехваченное исключение 'Exception' с сообщением 'Деление на ноль . ' в W: \ www \ test.php: 4 Трассировка стека: # 0 W: \ www \ test.php (11): inverse (0) # 1 {main}, брошенная в W: \ www \ test.php в строке 4 Я действительно понятия не имею, что там происходит ... может быть, неправильная конфигурация PHP?
Krassi
1
Некоторые старые версии расширений вызывали проблемы с обработкой исключений. 5.2.3 устарело, и за ошибкой может быть ошибка. Можете ли вы обновить PHP? UniServer 3.5 также довольно старый, учитывая, что текущая производственная версия - 5.5. 3.5 - это опечатка?
outis
1
Глядя на информацию о выпуске UniServer ( wiki.uniformserver.com/index.php/… ), можно сказать , что 3.5 явно не опечатка. Обновитесь до UniServer 5.5 и попробуйте снова использовать образец кода.
outis
1
outis, спасибо за подсказку :). Это то, что я тогда сделал - перешел на XAMPP (не нравится новая версия UniServer). 3.5 - это не опечатка, но сервер работал у меня отлично, поэтому я никогда не стал его обновлять.
Krassi 09

Ответы:

219

У меня была именно эта проблема, когда казалось, что я даже скопировал имя исключения, но оно не уловило его. Оказалось, что это была моя глупая ошибка, но я подумал, что должен опубликовать свое дело здесь на случай, если кто-то еще окажется в такой же ситуации.

У меня был исключение в моем пространстве имен и сценарий был в пространстве имен B . Проблема заключалась в том, что у меня было A \ MyException, которое равно (в PHP) \ B \ A \ MyException (потому что мой скрипт находится в пространстве имен с именем B !). Все, что мне нужно было сделать, чтобы исправить это, - это добавить обратную косую черту (или как там она называется) к имени исключения, чтобы оно выглядело так: \ A \ MyException

Пиюсн
источник
7
Большое спасибо за размещение этого сообщения, потому что я бы несколько дней не осознавал своей ошибки.
типу
79
Это решило мою проблему, должен быть простой блок отложенного перехвата в коде с пространством имен catch (\Exception $e). Без обратной косой черты Exceptionспецифичен для пространства имен и не будет сопоставлен (или пойман).
joemaller
3
Спасибо, что разместили это!
keepkimi
2
Спасибо, что разместили это, я только что провел последние несколько часов, сходя с ума от того, почему мой блок catch не работает. Крупный фейспалм.
Митч
4
Ура! Спас мой день (и нейроны ...) :)
овощ
68

Довольно старый вопрос, но ...

У меня тоже была эта проблема (и именно так я нашел этот пост), но простой эксперимент позволил мне найти решение. Просто попробуйте сменить Exceptionна \Exception. Сработало у меня!

РЕДАКТИРОВАТЬ:

Как указал Сиванн в комментариях, использование пространства имен должно делать то же самое. Поэтому просто поставьте use \Exception as Exception;перед объявлением класса.

Enethion
источник
Гениально! :) Наверное, мне потребовались бы часы, чтобы понять, просто не думал о пространстве имен. Спасибо!
Александр Гильманов,
Да! также: "использовать \ Exception как исключение;" вверху делает то же самое.
sivann
@ sii-anik Попробуйте использовать пространство имен, как написал sivann.
Enethion
просто use Exception;должен это сделать
Диего
32

Попробуйте поставить catch(\Exception $e)вместо catch(Exception $e). Если вы используете код, о котором не очень хорошо знаете, или - особенно - если вы используете фреймворк, он может переопределить исключение PHP по умолчанию одним своим собственным, и поэтому вы можете пойти по неправильному пути и получить нежелательный результат. Если вы просто поставили \Exception, то вы точно поймаете базовое исключение PHP.

Владимир Деспотович
источник
@crassi, ты попробовал мое предложение?
Владимир Деспотович
2
это сделало это для меня
cljk
20

Вы не можете использовать типичные блоки try {} catch {} в PHP, как вы могли бы это сделать на другом языке, таком как C # (Csharp).

Если вы сделаете это:

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

Вы не увидите "Понятно!" сообщение никогда. Зачем? Просто потому, что PHP всегда нужно «выбросить» исключение. Вам нужно установить собственный обработчик ошибок и выбросить с ним исключение.

См. Функцию set_error_handler : http://php.net/manual/es/function.set-error-handler.php

Ровинсон Гальего
источник
6
Это не то же самое;) Вам нужно было самому сгенерировать исключение, и именно об этом я сказал (<< Это просто потому, что PHP всегда нужно, чтобы исключение было "выброшено" >>) @JaredFarrish
Rowinson Gallego
Да, но как это не то же самое?
Джаред Фарриш,
Эта ссылка мертва, но я нашел ее полезной: w3schools.com/php/func_error_set_error_handler.asp
Loathing
В PHP версии 7.3.9 $number = 5/0;исключение не возникает. $numberустановлено быть INF.
virtualmic
6

Я начну с того, что у вас есть опечатка в имени исключения, которое вы перехватываете / бросаете, но если ваш код точно такой же, я не совсем уверен, что происходит.

Попробуйте следующую модификацию исходного сценария и вставьте свои результаты. Это поможет лучше диагностировать вашу проблему.

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

У меня была такая же проблема со следующими конфигурациями,

PHP 5.2.14 (cli) (построено: 12 августа 2010 г., 17:32:30) Copyright (c) 1997-2010 PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2010 Zend Technologies с eAccelerator v0.9.5. 1 , Copyright (c) 2004-2006 eAccelerator, автор: eAccelerator

Решение состоит в том, чтобы либо отключить eAccelerator, либо обновить его. Я попробовал оба, и оба исправления сработали. Об ошибке сообщается здесь https://eaccelerator.net/ticket/242 (NB. Firefox жалуется на свой сертификат SSL).

Теперь я выполняю попытку правильно поймать со следующими конфигурациями,

PHP 5.2.4 (cli) (построено: 16 октября 2007 г., 09:13:35) Copyright (c) 1997-2007 PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies с eAccelerator v0.9.6. 1 , Copyright (c) 2004-2010 eAccelerator, автор: eAccelerator

Явар
источник
3

в Xdebug есть настройка:

xdebug.show_exception_trace = 1

Это заставит php выводить исключения даже в блоке try catch. Превратите это в0

user2950254
источник
2
В моем случае мне пришлось полностью отключить модуль xdebug (изменения xdebug.show_exception_trace было недостаточно).
Thomas Sahlin
Спасибо за напоминание. Некоторое время я был полностью сбит с толку.
Брайан Литцингер
3

Если вы используете PHP 7, вам может понадобиться Throwable вместо Exception

user5528384
источник
Это довольно старый пост. Обратите внимание на дату в теме, прежде чем вы решите ответить. Кроме того, ваш ответ не очень полезен, так как он: - не полный - без объяснения причин
monofone
1
Объяснение заключается в том, что PHP7 использует Throwable вместо Exception. Это обсуждение было первым, которое я обнаружил, когда столкнулся с проблемой и хотел внести свой вклад. Подобные комментарии - причины, по которым Stack не подходит для сообщества.
user5528384
1
я не собирался вас обидеть. Это сообщение появилось в очереди на просмотр «Первые сообщения», и, на мой взгляд, было бесполезно размещать ответ на довольно старый вопрос. И на момент написания книги Question Throwable даже не был изобретен в мире PHP. Было бы полезно, если вы напишете в своем ответе, что Throwable - это интерфейс, реализованный с помощью Exception (и Error), и поэтому его тоже можно поймать. Но это не дополнение к Исключению.
monofone
1

TL; DR; убедитесь, что у вас есть use Exception;поверх обоих файлов php

Г-н Хилис
источник
0

Я тоже это переживаю. Я прочитал комментарий от Rowinson Gallego, в котором должно быть выбрано состояние Exception. Поэтому я изменил свой код с:

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

в:

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

Оно работает.

Фаузи Адриансьях
источник