2009-08-06 33 views
266

Tôi cần phải nắm bắt một số cảnh báo được đưa ra từ một số chức năng gốc của php và sau đó xử lý chúng.Tôi có thể thử/bắt cảnh báo không?

Cụ thể:

array dns_get_record (string $hostname [, int $type= DNS_ANY [, array &$authns [, array &$addtl ]]]) 

Nó ném một cảnh báo khi truy vấn DNS thất bại.

try/catch không hoạt động vì cảnh báo không phải là ngoại lệ.

bây giờ tôi có 2 lựa chọn:

  1. set_error_handler có vẻ như quá mức cần thiết bởi vì tôi phải sử dụng nó để lọc tất cả các cảnh báo trong trang (? Là đúng này);

  2. Điều chỉnh báo cáo/hiển thị lỗi để các cảnh báo này không được lặp lại với màn hình, sau đó kiểm tra giá trị trả về; nếu đó là false, không tìm thấy bản ghi nào cho tên máy chủ.

Thực tiễn tốt nhất ở đây là gì?

+1

http://stackoverflow.com/questions/136899/suppress-error-with-operator-in-php là một cuộc thảo luận tốt về những thứ như thế này. – Mez

+0

có câu trả lời bên dưới đã bị xóa? hoặc bởi chủ sở hữu hoặc bởi ai đó? – user121196

+0

cũng xem: http://stackoverflow.com/questions/1087365 – dreftymac

Trả lời

293

Set và khôi phục xử lý lỗi

Một khả năng là để thiết lập xử lý lỗi của riêng bạn trước khi cuộc gọi và khôi phục xử lý lỗi trước sau với restore_error_handler().

set_error_handler(function() { /* ignore errors */ }); 
dns_get_record(); 
restore_error_handler(); 

Bạn có thể xây dựng dựa trên ý tưởng này và viết trình xử lý lỗi có thể sử dụng lại để ghi lại lỗi cho bạn.

set_error_handler([$logger, 'onSilencedError']); 
dns_get_record(); 
restore_error_handler(); 

Quay lỗi vào trường hợp ngoại lệ

Bạn có thể sử dụng set_error_handler() và lớp ErrorException để biến tất cả các lỗi php vào trường hợp ngoại lệ.

set_error_handler(function($errno, $errstr, $errfile, $errline, array $errcontext) { 
    // error was suppressed with the @-operator 
    if (0 === error_reporting()) { 
     return false; 
    } 

    throw new ErrorException($errstr, 0, $errno, $errfile, $errline); 
}); 

try { 
    dns_get_record(); 
} catch (ErrorException $e) { 
    // ... 
} 

Điều quan trọng cần lưu ý khi sử dụng xử lý lỗi của riêng bạn là nó sẽ bỏ qua các thiết lập error_reporting và vượt qua tất cả các lỗi (thông báo, cảnh báo, vv) để xử lý lỗi của bạn. Bạn có thể đặt đối số thứ hai trên set_error_handler() để xác định loại lỗi nào bạn muốn nhận hoặc truy cập cài đặt hiện tại bằng cách sử dụng ... = error_reporting() bên trong trình xử lý lỗi.

cấm mức cảnh báo

Một khả năng khác là để ngăn chặn các cuộc gọi với các nhà điều hành @ và kiểm tra giá trị trở lại của dns_get_record() sau đó. Nhưng tôi khuyên bạn nên chống lại điều này là lỗi/cảnh báo được kích hoạt để được xử lý, không bị đàn áp.

+3

có nên đặt trình xử lý lỗi của riêng tôi ngay trước khi gọi hàm, sau đó restore_error_handler khi kiểm tra lỗi được thực hiện không? – user121196

+2

sẽ là chủ đề an toàn nếu có nhiều yêu cầu đồng thời và mỗi yêu cầu thực hiện 1.set_error_handler(). 2.doit 3.restore_error_handler? – user121196

+1

1. nếu đây là thực hành tốt? Tôi thực sự không biết. nhưng nếu các dudes từ Zend sử dụng phương pháp này, nó có thể không thực sự là xấu. 2. mỗi yêu cầu là khép kín, vì vậy sẽ không có bất kỳ vấn đề. –

4

Bạn có lẽ nên cố gắng loại bỏ hoàn toàn cảnh báo, nhưng nếu không thể, bạn có thể thêm cuộc gọi với @ (tức là @dns_get_record (...)) và sau đó sử dụng bất kỳ thông tin nào bạn có thể tìm ra nếu cảnh báo xảy ra hay không.

2

Nếu dns_get_record() không thành công, cần trả lại FALSE, vì vậy bạn có thể chặn cảnh báo bằng @ và sau đó kiểm tra giá trị trả về.

3

Normaly bạn không bao giờ nên sử dụng @ trừ khi đây là giải pháp duy nhất. Trong trường hợp cụ thể đó, hàm dns_check_record nên được sử dụng đầu tiên để biết liệu bản ghi có tồn tại hay không.

24

Hãy cẩn thận với nhà điều hành @ - trong khi nó ngăn chặn cảnh báo, nó cũng ngăn chặn các lỗi nghiêm trọng. Tôi đã dành rất nhiều thời gian để gỡ rối một vấn đề trong một hệ thống mà ai đó đã viết @mysql_query('...') và vấn đề là hỗ trợ mysql không được nạp vào PHP và nó đã ném một lỗi nghiêm trọng chết người. Nó sẽ được an toàn cho những thứ mà là một phần của lõi PHP nhưng xin vui lòng sử dụng nó một cách cẩn thận.

[email protected]:~$ php -a 
Interactive shell 

php > echo @something(); // this will just silently die... 

Không có thêm đầu ra - may mắn gỡ lỗi này!

[email protected]:~$ php -a 
Interactive shell 

php > echo something(); // lets try it again but don't suppress the error 
PHP Fatal error: Call to undefined function something() in php shell code on line 1 
PHP Stack trace: 
PHP 1. {main}() php shell code:0 
[email protected]:~$ 

Lần này chúng ta có thể thấy tại sao nó không thành công.

107

Các giải pháp mà thực sự công trình bật ra được thiết lập xử lý lỗi đơn giản với E_WARNING tham số, như vậy:

set_error_handler("warning_handler", E_WARNING); 
dns_get_record(...) 
restore_error_handler(); 

function warning_handler($errno, $errstr) { 
// do something 
} 
+1

giải pháp rất thanh lịch. CẬP NHẬT! :) –

+3

cũng ẩn danh 'có thể gọi được 'có thể được sử dụng ở đây thay vì chuỗi có khai báo hàm –

+0

Cảm ơn, nhưng làm thế nào tôi có thể loại bỏ trình xử lý lỗi sau khối quan trọng? –

5

Tôi muốn thử/bắt một cảnh báo, nhưng đồng thời giữ cho cảnh báo thông thường/ghi nhật ký lỗi (ví dụ: /var/log/apache2/error.log); mà người xử lý phải trả lại false. Tuy nhiên, kể từ khi "ném mới ..." tuyên bố về cơ bản làm gián đoạn việc thực hiện, người ta thì cũng phải thực hiện "quấn trong chức năng" lừa, cũng đã thảo luận trong:

Is there a static way to throw exception in php

Hoặc, trong ngắn gọn:

function throwErrorException($errstr = null,$code = null, $errno = null, $errfile = null, $errline = null) { 
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline); 
    } 
    function warning_handler($errno, $errstr, $errfile, $errline, array $errcontext) { 
    return false && throwErrorException($errstr, 0, $errno, $errfile, $errline); 
    # error_log("AAA"); # will never run after throw 
    /* Do execute PHP internal error handler */ 
    # return false; # will never run after throw 
    } 
    ... 
    set_error_handler('warning_handler', E_WARNING); 
    ... 
    try { 
    mkdir($path, 0777, true); 
    } catch (Exception $e) { 
    echo $e->getMessage(); 
    // ... 
    } 

EDIT: sau khi kiểm tra chặt chẽ hơn, nó quay ra nó không hoạt động là: "return false && throwErrorException ..." sẽ, về cơ bản, không ném ngoại lệ, và chỉ cần đăng nhập các bản ghi lỗi; loại bỏ phần "false &&", như trong "return throwErrorException ...", sẽ làm cho ngoại lệ ném công việc, nhưng sau đó sẽ không đăng nhập vào error_log ... Tôi vẫn giữ bài đăng này, mặc dù, vì tôi chưa thấy hành vi này được ghi lại ở nơi khác.

-2

Tôi chỉ khuyên bạn nên sử dụng @ để chặn cảnh báo khi hoạt động chuyển tiếp thẳng (ví dụ: $ prop = @ ($ cao/($ width - $ depth)); để bỏ qua phân chia bằng 0 cảnh báo). Tuy nhiên trong hầu hết các trường hợp, tốt hơn là xử lý.

+1

Đây là một lần bạn chắc chắn không muốn sử dụng @ - bạn có quyền kiểm soát hoạt động và có thể kiểm tra xem đó là một bộ phận bằng 0 hay không trước khi thực hiện. – Eborbob

0

hãy thử kiểm tra xem nó có trả về một số giá trị boolean không, sau đó bạn có thể đặt nó như một điều kiện. Tôi gặp phải điều này với oci_execute (...) đã trả lại một số vi phạm với các khóa duy nhất của tôi.

ex. 
oci_parse($res, "[oracle pl/sql]"); 
if(oci_execute){ 
...do something 
} 
Các vấn đề liên quan