Спроба / зловити блок у PHP не ловить виняток


97

Я намагаюся запустити цей Приклад №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
Чи можете ви показати нам свій код? Єдиною помилкою, яку ви можете зробити, щоб отримати цю помилку, є виявлення неправильного винятку (або жодного).
Таммо

2
Код ТОЧНО однаковий (я щойно додав нові рядки) ... все одно я скопіював код ще раз у тестовий файл і ось те саме повідомлення про помилку: 0,2 Фатальна помилка: Невизначений виняток "Виняток" з повідомленням "Відділення на нуль '. у W: \ www \ test.php: 4 Слід стека: # 0 W: \ www \ test.php (11): обернено (0) # 1 {main} закинуто W: \ www \ test.php по лінії 4 Я справді не уявляю, що там відбувається ... можливо, неправильна конфігурація PHP?
Крассі

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 - це не друкарська помилка, але сервер для мене працював ідеально, тому я ніколи не турбувався його оновленням.
Крассі

Відповіді:


218

Я просто мав цю точну проблему, коли здавалося, що навіть скопіював назву винятку, і все-таки це не зрозуміло. Виявилося, це моя дурна помилка, але я подумав, що я повинен розмістити свою справу тут, якщо в цій же ситуації є хтось інший.

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


7
велике дякую за повідомлення про це, бо я пройшов би кілька днів, не усвідомлюючи своєї помилки.
типу

79
Це вирішило мою проблему, простий ледачий блок лову в просторі коду повинен бути catch (\Exception $e). Без зворотної косої риси Exceptionхарактерно для простору імен і не буде відповідати (або спіймано).
joemaller

3
Дякуємо, що опублікували це!
Keepkimi

2
Дякую, що ви розмістили це повідомлення, я тільки що провів останні години, божеволіючи, чому мій блок лову не працював. Основна обличчя.
Мітч

4
Ура! Врятував мій день (і нейрони ...) :)
овоч

67

Досить давнє запитання, проте ...

У мене була і ця проблема (і саме так я знайшов цю посаду), але просто простий експеримент дозволив мені знайти рішення. Просто спробуйте змінити Exceptionна \Exception. Працювали для мене!

Редагувати:

Як в коментарях зазначив Сіванн, використання простору імен повинно робити те саме. Тож просто поставте use \Exception as Exception;перед оголошенням вашого класу.


Блискуче! :) Напевно, знадобиться мені години, щоб розібратися, просто не думав про пробіг імен. Дякую!
Олександр Гільманов

Так! також: "використовувати \ Виняток як виняток;" зверху робить те саме.
sivann

@ sii-anik Спробуйте використовувати простір імен так, як написав sivann.
Енетіон

просто use Exception;слід це зробити
Дієго

Спасибі! @Enethion
Noamway

32

Спробуйте поставити catch(\Exception $e)замість catch(Exception $e). Якщо ви використовуєте код, про який ви не дуже добре знаєте, або - особливо - якщо ви використовуєте фреймворк, він може замінити виняток PHP за замовчуванням одним із його власних, і тому ви можете піти в неправильний шлях і отримати небажаний результат. Якщо ви просто помітили \Exception, то ви впевнені, що переймаєте базовий виняток PHP.


@crassi, ти спробував мою пропозицію?
Володимир Деспотович

2
це зробило це для мене
cljk

20

Ви не можете використовувати типові блоки {{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
огиду

У PHP версії 7.3.9 $number = 5/0;не виняток. $numberвстановлено INF.
віртуальна

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) Авторське право (c) 1997-2010 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2010 Zend Technologies with 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 eAcecelerator, eAccelerator



3

у Xdebug є налаштування:

xdebug.show_exception_trace = 1

Це змусить php виводити винятки навіть у блоці try catch. Поверніть це0


2
У моєму випадку мені довелося повністю вимкнути модуль xdebug (змінити xdebug.show_exception_trace було недостатньо).
Томас Салін

Дякуємо за це нагадування. Я якийсь час був ретельно розгублений.
Брайан Літцінгер

3

Якщо ви використовуєте PHP 7, вам може знадобитися Throwable замість винятку


Це досить стара публікація. Погляньте на дату теми, перш ніж ви вирішите відповісти. Окрім цього, ваша відповідь не дуже корисна, оскільки така: - не повна - немає пояснення, чому
monofone

1
Пояснення полягає в тому, що PHP7 використовує Throwable замість винятку. Ця дискусія була першою, яку я знайшов, коли зіткнувся з проблемою і хотів внести свій внесок. Такі коментарі є причинами, чому Stack не є дружнім для спільноти.
користувач5528384

1
не було у мене наміру образити вас. Ця публікація з’явилася у черзі на перегляд «Перших дописів», і, на мою думку, не було корисно розміщувати відповідь на досить старе запитання. А на момент написання «Питання, яке можна кидати» навіть не було винайдено у світі PHP. Було б корисно, якщо ви напишете у відповідь, що Throwable - це інтерфейс, реалізований винятком (і помилкою), і, таким чином, його можна також наздогнати. Але це не є доповненням до Винятку.
монофон



0

Я також переживаю це. Я прочитав коментар Ровінсона Гальєго, в якому говориться про виняток. Тому я змінив свій код з:

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

Це працює.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.