2011-10-21 53 views
10

Tôi có một tập lệnh có trình xử lý ngoại lệ. Trình xử lý ngoại lệ này làm sạch một vài kết nối, trước khi tập lệnh thoát sau khi ngoại lệ.Ném ngoại lệ trong bộ xử lý ngoại lệ

Tôi muốn ném lại ngoại lệ từ trình xử lý ngoại lệ này để xử lý bởi trình xử lý ngoại lệ cuối cùng của PHP, nơi lỗi được ghi vào nhật ký lỗi của PHP hoặc bất kỳ giá trị mặc định nào, như được định cấu hình PHP.ini.

Thật không may, điều này không có vẻ như một khả năng, như được nêu ở đây:

http://www.php.net/manual/en/function.set-exception-handler.php#68712

Will cause a Fatal error: Exception thrown without a stack frame

Có một cách khác để bong bóng lỗi lên stack để PHP xử lý nó sau khi ngoại lệ của tôi xử lý được thực hiện làm sạch?

+0

Sử dụng một handler tùy chỉnh ngoại lệ vẫn sẽ kích hoạt một Erro gây tử vong r và do đó ghi lại lỗi. – netcoder

+0

Tại sao bạn không [chỉ ném ngoại lệ một lần nữa] (http://stackoverflow.com/questions/7856173/throwing-exception-within-exception-handler/7939492#7939492) từ trình xử lý của bạn? Nó hoạt động nếu bạn biết làm thế nào. Và nó sẽ kích hoạt trình xử lý cuối cùng của PHP mà bạn đang tìm kiếm. – hakre

+0

Tôi đã thấy điều này trước đây (và khuyên bạn nên khôi phục trình xử lý lỗi) nhưng tôi không thể tái sản xuất ngay bây giờ! Vấn đề này có phải là một phần của phiên bản cài đặt PHP/.ini không? – jlb

Trả lời

12

Bạn không thể ném lại từ trình xử lý ngoại lệ, tuy nhiên, có những nơi khác bạn có thể. Ví dụ, bạn có thể bỏ vài việc tái ném từ xử lý bằng cách đóng gói mọi thứ vào một lớp học riêng của nó và sau đó sử dụng __destruct() chức năng (PHP 5.3, Demo):

<?php 

class ExceptionHandler 
{ 
    private $rethrow; 
    public function __construct() 
    { 
     set_exception_handler(array($this, 'handler')); 
    } 
    public function handler($exception) 
    { 
     echo "cleaning up.\n"; 
     $this->rethrow = $exception; 
    } 
    public function __destruct() 
    { 
     if ($this->rethrow) throw $this->rethrow; 
    } 
} 

$handler = new ExceptionHandler; 

throw new Exception(); 

Đặt này vào log lỗi của tôi:

[29-Oct-2011 xx:32:25] PHP Fatal error: Uncaught exception 'Exception' in /.../test-exception.php:23 
Stack trace: 
#0 {main} 
thrown in /.../test-exception.php on line 23 
+1

Xem thêm, phần nào liên quan đến '__destruct': [Làm thế nào để xác định rằng tập lệnh PHP đang trong giai đoạn chấm dứt?] (Http://stackoverflow.com/q/6227611/367456) – hakre

+0

Cảm ơn @hakre, của bạn giải pháp hoạt động. Nhiều hơn một cách giải quyết hơn tôi đã hy vọng, nhưng tôi hiểu tại sao điều này là cần thiết. – Brad

+0

Xin chào Brad, cảm ơn vì sự chấp nhận. Tôi thích điều này "workaround" nhiều hơn so với đề xuất trên các ý kiến ​​người dùng trên php.net để tạo ra các mục đăng nhập lỗi trên của riêng mình. Tại sao lại phát minh ra bánh xe? Tôi đã thử cũng với chức năng đăng ký tắt máy, nhưng điều này ở đây tôi thích tốt hơn. – hakre

6

Chỉ cần bắt ngoại lệ và tự ghi nhật ký, sau đó quay lại.

try { 
    $foo->doSomethingToCauseException(); 
} catch (Exception $e) { 
    error_log($e->getMessage()); 
    throw $e; 
} 

Nếu bạn lướt lên đến đỉnh và PHP không thể xử lý, nó sẽ dẫn đến ngoại lệ không bị bắt buộc.

+0

Một ngoại lệ không thể bắt buộc sẽ ổn với tôi. Tôi muốn bong bóng tất cả lên đến đỉnh.Tôi đang tự khai thác lỗi ngay bây giờ (sử dụng phương pháp chính xác mà bạn mô tả), nhưng thay vì để PHP xử lý nó, để nhất quán. – Brad

+0

Tôi hiểu. Tôi cũng tò mò về điều này. Theo kinh nghiệm của tôi, cách duy nhất PHP xử lý các ngoại lệ là làm cho trang phát nổ, lol. –

3

Will cause a Fatal error: Exception thrown without a stack frame

Lỗi này có nghĩa là ngoại lệ của bạn được ném từ mã không phải là một phần của tập lệnh (theo như PHP biết). Ví dụ về mã như vậy bao gồm bộ xử lý ngoại lệ tùy chỉnh với set_exception_handler() và bất kỳ phương thức hủy lớp nào. Không có lựa chọn nào khác ngoài việc KHÔNG ném một ngoại lệ từ mã như vậy.

Nếu bạn muốn xử lý lỗi gốc PHP, tôi khuyên bạn nên gọi trigger_error() để thay thế. Nó sẽ ghi lại lỗi nếu bạn không có trình xử lý lỗi tùy chỉnh và bạn sử dụng loại lỗi thích hợp. Ví dụ: E_USER_ERROR sẽ ổn.

+0

Hoặc [chỉ ném ngoại lệ một lần nữa] (http://stackoverflow.com/questions/7856173/throwing-exception-within-exception-handler/7939492#7939492) tùy thuộc vào cấu hình sẽ cung cấp cho backtrace thích hợp. – hakre

+0

hakre: chỉ cần thử nó (ném * bất cứ thứ gì * từ bên trong một trình xử lý ngoại lệ tùy chỉnh hoặc phương thức hủy lớp) - bạn sẽ thấy rằng nó không hoạt động. Nó không quan trọng nếu bạn sử dụng xdebug hay không. –

+1

Mikko, trông giống như [câu trả lời của tôi] (http://stackoverflow.com/questions/7856173/throwing-exception-within-exception-handler/7939492#7939492) yêu cầu PHP 5.3. Xem http://codepad.viper-7.com/jamrqP – hakre

1

Chỉ rethrow các ngoại lệ như một RuntimeException và nó sẽ giữ stacktrace :)

try { 
    // bad exception throwing code 
} catch (Exception $e) { 
    throw new RuntimeException($e->getMessage(), $e->getCode(), $e); 
}