<rmcreative>

RSS

Как выкинуть исключение в __toString и к чему это приведёт

20 марта 2010

Как известно, исключения кидать в __toString() PHP запрещает. Выглядит это не очень-то логично, но запрещено не просто так. Вообще __toString() — штука крайне нестабильная и сложная в отладке.

Оказалось, что исключение в __toString() выкинуть всё-таки можно при помощи своего обработчика ошибок и приведёт это довольно неожиданным результатам.

Вот такой код

class X {
    function __toString(){
         $this->test();
    }
 
    function test(){
         explode(',', new self);
    }
}
 
echo new X();

выдаст нам вполне понятный «Catchable fatal error: Object of class X could not be converted to string». Добавим свой обработчик ошибок, конвертирующий их в исключения.

Генерация исключений вместо ошибок популярна из за возможности получить стек вызовов и другую полезную отладочную информацию и используются в большом количестве фреймворков. Например, в Yii.

set_error_handler('handle_error');
 
function handle_error($errno, $errstr, $errfile, $errline, $errcontext){
    throw new Exception('test');
}

Выполнение, проходившее ранее более-менее корректно, теперь вызывает мощное размножение процессов и тредов Apache и за пару-тройку запусков роняет его вовсе.

Комментарии RSS

  1. №2416
    dkrnl
    dkrnl 20 марта 2010 г., 10:43:27

    Чтобы не мучатся с отладкой toString мы делаем примерно так:

    public function __toString()

    ...

    {

    try

    {

    $this->render();
    
    

    }

    catch(Exception $e)

    {

    Aquilon_Catcher::throwException($e);
    
    

    }

    }

    ...

    public function throwException(Exception $e)

    {

    ...

    echo $e;

    exit;

    }

    ...

  2. №2417
    Sam
    Sam 20 марта 2010 г., 12:44:03

    Меня подобный подход не спас — апачу всё так же плохело. Не отлавливается ли исключение или происходит что-то иное пока не выяснял.

  3. №2418
    AmdY
    AmdY 20 марта 2010 г., 14:40:10

    Из __toString вообще пока нельзя выбрасывать исключения. И метод вовсе не предполагалось использовать в методах типа explode, только для echo, print :( http://www.php.net/manual/en/language.oop5.magic.php#language.oop5.magic.tostring

  1. Почта опубликована не будет.

  2. Можно использовать синтаксис Markdown или HTML.

  3. Введите ответ в поле. Щёлкните, чтобы получить другую задачу.