Làm cách nào để tôi có thể gặp “lỗi nghiêm trọng có thể bắt gặp” trên gợi ý loại PHP?


96

Tôi đang cố gắng triển khai Gợi ý kiểu của PHP5 trên một lớp của mình,

class ClassA {
    public function method_a (ClassB $b)
    {}
}

class ClassB {}
class ClassWrong{}

Cách sử dụng đúng:

$a = new ClassA;
$a->method_a(new ClassB);

lỗi sản xuất:

$a = new ClassA;
$a->method_a(new ClassWrong);

Lỗi nghiêm trọng có thể bắt được: Đối số 1 được truyền tới ClassA :: method_a () phải là một phiên bản của ClassB, phiên bản ClassWrong đã cho ...

Có thể bắt lỗi đó không (vì nó nói "có thể bắt được")? và nếu có, làm thế nào?


4
Để tham khảo trong tương lai: Các ngoại lệ trong công cụ (đối với PHP 7) - Bắt đầu với PHP 7, có thể mắc các lỗi nghiêm trọng. Đây cũng là cho đây thảo luận “lỗi nghiêm trọng catchable” ( E_RECOVERABLE_ERROR) vì đây được đánh bắt đầu với PHP 7 ..
hakre

Câu trả lời:


113

Cập nhật: Đây không phải là một lỗi nghiêm trọng có thể mắc phải nữa trong php 7. Thay vào đó, một "ngoại lệ" được ném ra. Một "ngoại lệ" (trong dấu ngoặc kép) không có nguồn gốc từ Exception mà là Error ; nó vẫn là một Throwable và có thể được xử lý bằng một khối try-catch thông thường. xem https://wiki.php.net/rfc/throwable-interface

Ví dụ

<?php
class ClassA {
  public function method_a (ClassB $b) { echo 'method_a: ', get_class($b), PHP_EOL; }
}
class ClassWrong{}
class ClassB{}
class ClassC extends ClassB {}


foreach( array('ClassA', 'ClassWrong', 'ClassB', 'ClassC') as $cn ) {
    try{
      $a = new ClassA;
      $a->method_a(new $cn);
    }
    catch(Error $err) {
      echo "catched: ", $err->getMessage(), PHP_EOL;
    }
}
echo 'done.';

bản in

catched: Argument 1 passed to ClassA::method_a() must be an instance of ClassB, instance of ClassA given, called in [...]
catched: Argument 1 passed to ClassA::method_a() must be an instance of ClassB, instance of ClassWrong given, called in [...]
method_a: ClassB
method_a: ClassC
done.

Câu trả lời cũ cho các phiên bản trước php7:
http://docs.php.net/errorfunc.constants cho biết:

E_RECOVERABLE_ERROR (số nguyên)
Lỗi nghiêm trọng có thể bắt được. Nó chỉ ra rằng một lỗi có thể nguy hiểm đã xảy ra, nhưng không khiến Động cơ ở trạng thái không ổn định. Nếu lỗi không được phát hiện bởi một xử lý do người dùng xác định (xem thêm set_error_handler () ), ứng dụng sẽ hủy bỏ vì nó là một E_ERROR.

xem thêm: http://derickrethans.nl/erecoverableerror.html

ví dụ

function myErrorHandler($errno, $errstr, $errfile, $errline) {
  if ( E_RECOVERABLE_ERROR===$errno ) {
    echo "'catched' catchable fatal error\n";
    return true;
  }
  return false;
}
set_error_handler('myErrorHandler');

class ClassA {
  public function method_a (ClassB $b) {}
}

class ClassWrong{}

$a = new ClassA;
$a->method_a(new ClassWrong);
echo 'done.';

bản in

'catched' catchable fatal error
done.

chỉnh sửa: Nhưng bạn có thể "biến" nó thành một ngoại lệ mà bạn có thể xử lý bằng khối try-catch

function myErrorHandler($errno, $errstr, $errfile, $errline) {
  if ( E_RECOVERABLE_ERROR===$errno ) {
    echo "'catched' catchable fatal error\n";
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
    // return true;
  }
  return false;
}
set_error_handler('myErrorHandler');

class ClassA {
  public function method_a (ClassB $b) {}
}

class ClassWrong{}

try{
  $a = new ClassA;
  $a->method_a(new ClassWrong);
}
catch(Exception $ex) {
  echo "catched\n";
}
echo 'done.';

xem: http://docs.php.net/ErrorException


1
Vì vậy, tất nhiên điều này hoạt động rất giống một lỗi nghiêm trọng, ngoại trừ khi bạn xem nhật ký máy chủ của mình, bạn sẽ không tìm thấy nó. Cảm ơn php: /
John Hunt

3
vì vậy nói cách khác, bạn không thể bắt lỗi có thể bắt được. Tuyệt vời!
Paul d'Aoust

@Paul điều gì đưa bạn đến kết luận này?
VolkerK

3
Ồ, ý tôi chỉ là nó không thể bắt được theo nghĩa truyền thống (sử dụng khối thử / bắt). Tôi chỉ cảm thấy khó chịu về PHP ngày hôm đó, vì vậy khi tôi phát hiện ra rằng nó 'có thể bắt được' theo một nghĩa hoàn toàn khác, tôi cảm thấy buộc phải bình luận. Không có gì chống lại câu trả lời tuyệt vời của bạn (thực tế là tôi đã ủng hộ); tất cả những gì tôi có là dành cho chính PHP!
Paul d'Aoust

Và tôi nghĩ rằng tôi đã bỏ qua một cái gì đó ;-) blog.codinghorror.com/php-sucks-but-it-doesnt-matter : D
VolkerK Ngày
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.