Nói chung, các phương thức riêng tư hoặc được bảo vệ sẽ không thể truy cập được bên ngoài lớp. Nhưng nếu bạn đang viết một bài kiểm tra đơn vị, bạn có thể phá vỡ quy tắc này
Đã cho lớp PHP với phương thức riêng
class Foo
{
private function bar[]: string
{
return 'baz';
}
}
Sự phản xạ
Sử dụng Reflection để gọi phương thức bên ngoài lớp
$reflectionClass = new ReflectionClass[Foo::class];
$reflectionMethod = $reflectionClass->getMethod['bar'];
$reflectionMethod->setAccessible[true];
$reflectionMethod->invoke[new Foo[]]; // 'baz'
Phản ánh hoạt động cho cả phương pháp riêng tư và được bảo vệ
Ngoài ra, điều này có thể được cấu trúc lại và đơn giản hóa thành
$reflectionClass = new ReflectionClass[Foo::class];
$reflectionMethod = $reflectionClass->getMethod['bar'];
$reflectionMethod->setAccessible[true];
$reflectionMethod->invoke[new Foo[]]; // 'baz'
2$reflectionMethod = new ReflectionMethod[Foo::class, 'bar'];
$reflectionMethod->setAccessible[true];
$reflectionMethod->invoke[new Foo[]]; // 'baz'
Để truyền đối số phương thức, hãy sử dụng ReflectionMethod. gọiArgs
$args = [1, 2, 3];
$reflectionMethod->invokeArgs[new Foo[], $args];
Đây là một hàm có thể tái sử dụng gọi một phương thức thể hiện của lớp
/**
* Calls object method with arguments.
*
* @param object $object
* @param string $method
* @param array $args
* @return mixed
*/
function callObjectMethod[object $object, string $method, array $args = []]
{
$reflectionMethod = new ReflectionMethod[get_class[$object], $method];
$reflectionMethod->setAccessible[true];
return $reflectionMethod->invokeArgs[$object, $args];
}
Điều này có nghĩa là bạn có thể gọi
$reflectionClass = new ReflectionClass[Foo::class];
$reflectionMethod = $reflectionClass->getMethod['bar'];
$reflectionMethod->setAccessible[true];
$reflectionMethod->invoke[new Foo[]]; // 'baz'
3callObjectMethod[new Foo[], 'bar']; // 'baz'
Thử nghiệm
Xem thay thế. nó
Các phương thức lớp PHP được khai báo
$reflectionClass = new ReflectionClass[Foo::class];
$reflectionMethod = $reflectionClass->getMethod['bar'];
$reflectionMethod->setAccessible[true];
$reflectionMethod->invoke[new Foo[]]; // 'baz'
4 không thể truy cập được bởi các lớp con, nhưng các lớp con có thể khai báo một phương thức có cùng tên mà không cần phải tuân thủ Nguyên tắc thay thế Liskov. PHP8. 0 thực thi nghiêm ngặt các chữ ký của phương thức, nhưng các phương thức của lớp $reflectionClass = new ReflectionClass[Foo::class];
$reflectionMethod = $reflectionClass->getMethod['bar'];
$reflectionMethod->setAccessible[true];
$reflectionMethod->invoke[new Foo[]]; // 'baz'
4 không bị ảnh hưởng bởi thay đổi nàyTyped Properties được giới thiệu trong PHP 7. 4 đã tuân theo các thay đổi tương tự và không bị thay đổi trong PHP 8. 0
Trước PHP 8. 0, nó không được phép thay đổi để thay đổi các cờ
Fatal error: Cannot override final method Foo::testFoo[] in .. on line ...
2 hoặc Fatal error: Cannot override final method Foo::testFoo[] in .. on line ...
3 của một phương thức lớp. Điều này được thay đổi trong PHP 8. 0, điều đó đảm bảo các phương thức $reflectionClass = new ReflectionClass[Foo::class];
$reflectionMethod = $reflectionClass->getMethod['bar'];
$reflectionMethod->setAccessible[true];
$reflectionMethod->invoke[new Foo[]]; // 'baz'
4 có thể thực sự riêng tư mà không cần tuân thủ các quy tắc kế thừa được thi hành từ [các] lớp chaTrong tất cả các phiên bản PHP, tham số phương thức lớp
4, kiểu trả về phương thức$reflectionClass = new ReflectionClass[Foo::class]; $reflectionMethod = $reflectionClass->getMethod['bar']; $reflectionMethod->setAccessible[true]; $reflectionMethod->invoke[new Foo[]]; // 'baz'
4 và kiểu thuộc tính lớp$reflectionClass = new ReflectionClass[Foo::class]; $reflectionMethod = $reflectionClass->getMethod['bar']; $reflectionMethod->setAccessible[true]; $reflectionMethod->invoke[new Foo[]]; // 'baz'
4 không được xác thực theo Nguyên tắc thay thế Liskov. Những thay đổi này trong PHP 8. 0 chỉ áp dụng cho các thay đổi trong các cờ$reflectionClass = new ReflectionClass[Foo::class]; $reflectionMethod = $reflectionClass->getMethod['bar']; $reflectionMethod->setAccessible[true]; $reflectionMethod->invoke[new Foo[]]; // 'baz'
8,Fatal error: Cannot override final method Foo::testFoo[] in .. on line ...
3 vàFatal error: Cannot override final method Foo::testFoo[] in .. on line ...
2 trong các phương thức của lớpFatal error: Cannot override final method Foo::testFoo[] in .. on line ...
Khai báo phương thức của lớp
$reflectionClass = new ReflectionClass[Foo::class];
$reflectionMethod = $reflectionClass->getMethod['bar'];
$reflectionMethod->setAccessible[true];
$reflectionMethod->invoke[new Foo[]]; // 'baz'
11 phát ra cảnh báo PHP tại thời điểm khai báo của lớp cha. Hành vi này khác với lỗi nghiêm trọng chỉ được kích hoạt nếu một lớp con cố gắng mở rộng/khai báo lại cùng một phương thức