Я только что реализовал пользовательскую ошибку с trigger_error()
, но проблема в том, что линия, которая вызывает trigger_error()
отображается в виде строки с ошибками в трассировке стека вызовов вместо вызывающей линии.
<?php
trait ClassProtection {
public function __get($name) {
$class_name = get_called_class();
trigger_error("Public property {$class_name}::\${$name} does not exist", E_USER_ERROR);
}
public function __set($name, $value) {
$class_name = get_called_class();
trigger_error("Public property {$class_name}::\${$name} does not exist and automatic creation has been disabled", E_USER_ERROR);
}
}
class SomeClass {
use ClassProtection;
public $foo = 1;
protected $bar = 2;
private $baz = 3;
}
$sc = new SomeClass;
// Try to access existing public property: should work
var_dump($sc->foo);
$sc->foo = 11;
// Try to access existing protected property: should not work - fatal error
var_dump($sc->bar);
$sc->bar = 12;
// Try to access existing private property: should not work - fatal error
var_dump($sc->baz);
$sc->baz = 13;
// Try to create new public property: should not work - fatal error
$sc->qux = 14;
var_dump($sc->qux);
С линией //use ClassProtection;
прокомментировал, это производит следующее:
C:\>php test_class_protection.php
int(1)
PHP Fatal error: Cannot access protected property SomeClass::$bar in C:\test_class_protection.php on line 28
PHP Stack trace:
PHP 1. {main}() C:\test_class_protection.php:0
Fatal error: Cannot access protected property SomeClass::$bar in C:\test_class_protection.php on line 28
Call Stack:
0.0000 127344 1. {main}() C:\test_class_protection.php:0
С линией use ClassProtection;
без комментариев он производит следующее:
C:\>php test_class_protection.php
int(1)
PHP Fatal error: Public property SomeClass::$bar does not exist in C:\test_class_protection.php on line 5
PHP Stack trace:
PHP 1. {main}() C:\test_class_protection.php:0
PHP 2. SomeClass->__get($name = 'bar') C:\test_class_protection.php:28
PHP 3. trigger_error('Public property SomeClass::$bar does not exist', 256) C:\test_class_protection.php:5
Fatal error: Public property SomeClass::$bar does not exist in C:\test_class_protection.php on line 5
Call Stack:
0.0000 127648 1. {main}() C:\test_class_protection.php:0
0.0000 128904 2. SomeClass->__get(string(3)) C:\test_class_protection.php:28
0.0000 129128 3. trigger_error(string(46), long) C:\test_class_protection.php:5
Обратите внимание, что здесь есть две дополнительные строки, которые бесполезны и фактически отвлекают при отладке. Я хочу, чтобы вторая ошибка выглядела как первая, кроме как с настроенным сообщением.
Кажется, я помню, как когда я работал с Perl, в нем был какой-то механизм доверенного кода, который предотвращал появление кода, помеченного как доверенный, в трассировке стека. Есть ли способ в PHP, чтобы скрыть последние один или два вызова в трассировке стека вызовов, не переписывая весь обработка ошибок рутина, чтобы она выглядела как стандартная ошибка PHP произошла на правильной строке?
В идеале я хотел бы получить копию трассировки стека, слегка изменить ее и вернуть в стандартный обработчик ошибок PHP.
Задача ещё не решена.
Других решений пока нет …