php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #67509 set_error_handler ignores class scope
Submitted: 2014-06-25 00:20 UTC Modified: 2014-06-25 09:55 UTC
From: tugrultopuz at gmail dot com Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 5.4.29 OS: Debian 7.2
Private report: No CVE-ID: None
 [2014-06-25 00:20 UTC] tugrultopuz at gmail dot com
Description:
------------
I tried to send static method of a class as the callback. 

Test script:
---------------
<?php

namespace My;

class Exception extends \Exception
{
    protected $context;
    
    public static function setErrorHandler()
    {
        set_error_handler('static::_errorHandler');
    }
    
    public static function restoreErrorHandler()
    {
        return restore_error_handler();
    }
    
    protected static function _errorHandler($number, $message, $file, $line, $context)
    {
        self::restoreErrorHandler();

        $exception = new static($message, $number);
        $exception->file = $file;
        $exception->line = $line;
        $exception->context = $context;

        throw $exception;
    }
}

\My\Exception::setErrorHandler();

try {
    trigger_error('My custom error!');
} catch (\My\Exception $ex) {
    echo 'Error Message:', $ex->getMessage();
}

\My\Exception::restoreErrorHandler();



Expected result:
----------------
Error Message: My custom error!

Actual result:
--------------
Warning: Invalid callback static::_errorHandler, cannot access static:: when no class scope is active in test.php on line 17

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-06-25 01:23 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2014-06-25 01:23 UTC] requinix@php.net
The error handler isn't executing until the error happens and that's long after scope has left the setErrorHandler() method. It cannot know what you meant by "static".

Specify the class name.

  set_error_handler(__CLASS__ . '::_errorHandler'); // or get_called_class()

Then you'll get an error about being unable to call a protected method, which you can resolve by making _errorHandler() public.
 [2014-06-25 09:55 UTC] tugrultopuz at gmail dot com
OK. I understood. Class scope should be on calling time instead of registering time.

Yes I can make the way that your solution. Going to be a little dirty.

It works like following

<?php

namespace My;

class Exception extends \Exception
{
    protected $context;
    
    public static function setErrorHandler()
    {
        set_error_handler('static::_errorHandler');
    }
    
    public static function restoreErrorHandler()
    {
        return restore_error_handler();
    }
    
    protected static function _errorHandler($number, $message, $file, $line, $context)
    {
        self::restoreErrorHandler();

        $exception = new static($message, $number);
        $exception->file = $file;
        $exception->line = $line;
        $exception->context = $context;

        throw $exception;
    }
    
    public static function triggerError($message)
    {
        trigger_error($message);
    }
}

\My\Exception::setErrorHandler();

try {
    \My\Exception::triggerError('My custom error!');
} catch (\My\Exception $ex) {
    echo $ex->getMessage();
}



\My\Exception::restoreErrorHandler();
 
PHP Copyright © 2001-2026 The PHP Group
All rights reserved.
Last updated: Tue Oct 06 21:00:01 2026 UTC