Thử / Bắt khối trong PHP không bắt được Ngoại lệ


97

Tôi đang cố chạy Ví dụ số 1 này từ trang này: 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";
?>

Tuy nhiên, thay vì đầu ra mong muốn, tôi nhận được:

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

Môi trường phát triển Tôi đang sử dụng là UniServer 3.5PHP 5.2.3


1
Bạn có thể cho chúng tôi xem mã của bạn không? Sai lầm duy nhất bạn có thể làm để gặp lỗi này là bắt nhầm ngoại lệ (hoặc không có).
Tammo

2
Mã hoàn toàn giống hệt nhau (tôi vừa thêm một số dòng mới) ... dù sao, tôi đã sao chép mã một lần nữa vào tệp thử nghiệm và đây là thông báo lỗi tương tự: 0.2 Lỗi nghiêm trọng: Không có ngoại lệ 'Ngoại lệ' với thông báo 'Chia cho số không . ' trong W: \ www \ test.php: 4 Dấu vết ngăn xếp: # 0 W: \ www \ test.php (11): inverse (0) # 1 {main} được đưa vào W: \ www \ test.php trên dòng 4 Tôi thực sự không biết chuyện gì đang xảy ra ở đó ... có thể cấu hình PHP bị lỗi?
Krassi

1
Một số phiên bản tiện ích mở rộng cũ hơn gây ra sự cố với việc xử lý ngoại lệ. 5.2.3 đã cũ và một lỗi có thể nằm sau lỗi. Bạn có thể nâng cấp PHP không? UniServer 3.5 cũng khá cũ, xét về phiên bản sản xuất hiện tại là 5.5. 3.5 có phải là lỗi đánh máy không?
outis

1
Nhìn vào thông tin phát hành UniServer ( wiki.uniformserver.com/index.php/… ), 3.5 rõ ràng không phải là lỗi đánh máy. Nâng cấp lên UniServer 5.5 và thử lại mã mẫu.
outis

1
outis, cảm ơn cho mẹo :). Đây là những gì tôi đã làm hồi đó - chuyển sang XAMPP (không thích phiên bản UniServer mới). 3.5 không phải là lỗi đánh máy, nhưng máy chủ hoạt động hoàn hảo đối với tôi nên tôi không bao giờ bận tâm đến việc nâng cấp nó.
Krassi

Câu trả lời:


217

Tôi chỉ gặp vấn đề chính xác này mà có vẻ như tôi thậm chí đã sao chép tên của ngoại lệ nhưng nó không bắt được. Hóa ra đó là sai lầm ngu ngốc của tôi nhưng tôi nghĩ mình nên đăng trường hợp của mình lên đây để phòng trường hợp có người khác ở cùng hoàn cảnh.

Tôi có ngoại lệ của tôi trong không gian tên của tôi được gọi là A và kịch bản đang ở trong một không gian tên gọi là B . Vấn đề là tôi có A \ MyException bằng (trong PHP) \ B \ A \ MyException (vì tập lệnh của tôi nằm trong không gian tên được gọi là B !). Tất cả những gì tôi phải làm để sửa nó là thêm dấu gạch chéo ngược (hoặc bất cứ thứ gì được gọi) vào tên ngoại lệ để nó trông giống như sau: \ A \ MyException


7
cảm ơn bạn rất nhiều vì đã đăng bài này bởi vì tôi đã có thể đi vài ngày mà không nhận ra sai lầm của mình.
tipu

79
Điều này đã giải quyết vấn đề của tôi, một khối bắt lười đơn giản trong mã không gian tên phải được catch (\Exception $e). Không có dấu gạch chéo ngược Exceptionlà đặc trưng cho không gian tên và sẽ không được khớp (hoặc bị bắt).
joemaller

3
Cảm ơn vì đã đăng bài này!
keepkimi

2
Cảm ơn bạn đã đăng bài này, tôi vừa mất vài giờ qua để tìm hiểu lý do tại sao khối bắt của tôi không hoạt động. Mặt chính.
Mitch

4
Chúc mừng! Lưu ngày của tôi (và tế bào thần kinh ...) :)
rau

67

Câu hỏi khá cũ, nhưng ...

Tôi cũng gặp sự cố này (và đó là cách tôi tìm thấy bài đăng này) nhưng chỉ cần thử nghiệm đơn giản đã cho phép tôi tìm ra giải pháp. Chỉ cần thử thay đổi Exceptionthành \Exception. Đã làm cho tôi!

BIÊN TẬP:

Như sivann đã chỉ ra trong các nhận xét, sử dụng không gian tên cũng sẽ làm điều tương tự. Vì vậy, chỉ cần đặt use \Exception as Exception;trước khai báo lớp của bạn.


Xuất sắc! :) Có lẽ tôi sẽ mất hàng giờ để tìm ra, chỉ là không nghĩ về không gian tên. Cảm ơn!
Alexander Gilmanov

Đúng! cũng: "use \ Exception as Exception;" ở trên cùng cũng làm điều tương tự.
sivann

@ sii-anik Hãy thử sử dụng không gian tên giống như sivann đã viết.
Enethion

chỉ use Exception;nên làm điều đó
Diego Ponciano

Cảm ơn bạn! @Enethion
Noamway

32

Cố gắng đặt catch(\Exception $e)thay vì catch(Exception $e). Nếu bạn đang sử dụng một mã mà bạn không biết rõ về nó, hoặc - đặc biệt - nếu bạn đang sử dụng một khung công tác, nó có thể ghi đè Ngoại lệ PHP mặc định bằng một trong những mã riêng của nó, và do đó bạn có thể đi đến sai đường dẫn và nhận được kết quả không mong muốn. Nếu bạn vừa đặt \Exception, thì bạn chắc chắn rằng bạn đang bắt được ngoại lệ PHP cơ bản.


@crassi, bạn đã thử gợi ý của tôi chưa?
Vladimir Despotovic

2
điều đó đã làm điều đó cho tôi
cljk

20

Bạn không thể sử dụng các khối try {} catch {} thông thường trong PHP như bạn có thể làm trong ngôn ngữ khác như C # (Csharp).

Nếu bạn làm điều này:

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

Bạn sẽ không thấy thông báo 'Đã hiểu!' tin nhắn không bao giờ. Tại sao? Đó chỉ là vì PHP luôn cần một Ngoại lệ để được "Thrown". Bạn cần thiết lập trình xử lý lỗi của riêng mình và đặt một Ngoại lệ với nó.

Xem hàm set_error_handler : http://php.net/manual/es/ Chức năng.set-error-handler.php


6
Đó là không giống nhau;) Bạn cần để ném một ngoại lệ bằng chính mình, và điều đó đã được những gì tôi nói (<< Đó là chỉ vì PHP luôn cần một ngoại lệ để được "ném" >>) @JaredFarrish
Rowinson Gallego

Có, nhưng nó không giống nhau như thế nào?
Jared Farrish

Liên kết đó đã chết, nhưng tôi thấy điều này hữu ích: w3schools.com/php/func_error_set_error_handler.asp
Loathing

Trong phiên bản PHP 7.3.9, $number = 5/0;không nêu ra một ngoại lệ. $numberđược thiết lập để được INF.
virtualmic

6

Mặc dù ban đầu của tôi là bạn có lỗi đánh máy trong tên của ngoại lệ bạn đang bắt / ném, nhưng nếu mã của bạn giống hệt nhau, tôi không chắc chính xác điều gì đang xảy ra.

Hãy thử sửa đổi tập lệnh gốc sau đây và dán kết quả của bạn. Nó sẽ giúp chẩn đoán vấn đề của bạn tốt hơn một chút.

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

Tôi đã gặp vấn đề tương tự với các cấu hình sau,

PHP 5.2.14 (cli) (xây dựng: 12/08/2010 17:32:30) Bản quyền (c) 1997-2010 Công cụ Zend của Nhóm PHP v2.2.0, Bản quyền (c) 1998-2010 Zend Technologies với eAccelerator v0.9.5. 1 , Bản quyền (c) 2004-2006 eAccelerator, bởi eAccelerator

Giải pháp là tắt eAccelerator hoặc cập nhật nó. Tôi đã thử cả hai và cả hai bản sửa lỗi đều hoạt động. Lỗi được báo cáo tại đây https://eaccelerator.net/ticket/242 (NB. Firefox phàn nàn về chứng chỉ SSL của họ).

Bây giờ tôi đang chạy, hãy thử bắt đúng cách với các cấu hình sau,

PHP 5.2.4 (cli) (xây dựng: 16 tháng 10 năm 2007 09:13:35) Bản quyền (c) 1997-2007 PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies với eAccelerator v0.9.6. 1 , Bản quyền (c) 2004-2010 eAccelerator, bởi eAccelerator



3

trong Xdebug có một cài đặt:

xdebug.show_exception_trace = 1

Điều này sẽ buộc php xuất ra các ngoại lệ ngay cả trong một khối try catch. Biến cái này thành0


2
Trong trường hợp của tôi, tôi đã phải tắt hoàn toàn mô-đun xdebug (thay đổi xdebug.show_exception_trace là không đủ).
Thomas Sahlin

Cảm ơn vì lời nhắc này. Tôi đã hoàn toàn bối rối trong một thời gian.
Brian Litzinger 23/03/18

3

Nếu bạn đang sử dụng PHP 7, bạn có thể cần Throwable thay vì Exception


Đây là một bài viết khá cũ. Hãy xem ngày của chủ đề trước khi bạn quyết định trả lời. Bên cạnh đó là câu trả lời của bạn không thực sự hữu ích vì nó là: - không đầy đủ - không giải thích tại sao
monofone

1
Lời giải thích là PHP7 sử dụng Throwable thay vì Exception. Cuộc thảo luận này là cuộc thảo luận đầu tiên tôi tìm thấy khi tôi gặp sự cố và tôi muốn đóng góp. Những nhận xét như thế này là lý do tại sao Stack không thân thiện với cộng đồng.
user5528384

1
nó không phải là ý định của tôi để xúc phạm bạn. Bài đăng này xuất hiện trong hàng đợi Đánh giá "Bài viết đầu tiên" và theo ý kiến ​​của tôi, việc đăng câu trả lời cho một câu hỏi khá cũ là không hữu ích. Và tại thời điểm viết câu hỏi, Câu hỏi có thể ném thậm chí còn chưa được phát minh trong thế giới PHP. Sẽ rất hữu ích nếu bạn viết trong bạn câu trả lời rằng Throwable là Giao diện được triển khai bởi Exception (và Error) và do đó cũng có thể được khắc phục. Nhưng nó không phải là một bổ sung cho một Ngoại lệ.
monofone


1

TLDR; đảm bảo rằng bạn có use Exception;ở trên cùng của cả hai tệp php


0

Tôi cũng đang trải qua điều này. Tôi đọc bình luận từ Rowinson Gallego rằng trạng thái Ngoại lệ phải được ném. Vì vậy, tôi đã sửa đổi mã của mình từ:

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

thành:

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

Nó hoạt động.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.