Caller Error Handlers

Caller Error Handlers are useful when a function implementer wants to “blame” function’s callers for errors occurring within the function. Normally, when error is triggered with trigger_error(), the error handler receives $file and $line pointing to the line of code where the trigger_error() was invoked. This can be easily changed with Caller Error Handlers, where the developer can easily point to current function’s caller or its caller’s caller, and so on.

Simple example with Caller Error Handler

The example uses the following symbols

1
2
use function Korowai\Lib\Context\with;
use function Korowai\Lib\Error\callerErrorHandler;

Our error handler will just output $file and $line it received from CallerErrorHandler.

1
2
3
4
5
function handler(int $severity, string $message, string $file, int $line) : bool
{
    printf("error occured at %s: %d: (%s)\n", basename($file), $line, $message);
    return true;
}

We’re now going to implement a function which triggers an error, but blames its caller for this error. This may be easily done with the CallerErrorHandler class.

1
2
3
4
5
6
7
function trigger()
{
    with(callerErrorHandler(handler::class))(function ($eh) {
        printf("trigger_error() called at: %s: %d\n", basename(__file__), __line__ + 1);
        @trigger_error("error message");
    });
}

Finally, we test our function with the following code

1
2
printf("trigger() called at: %s: %d\n", basename(__file__), __line__ + 1);
trigger();

The outputs from the above example are

  • stdout:
1
2
3
trigger() called at: caller_error_handler.php: 28
trigger_error() called at: caller_error_handler.php: 21
error occured at caller_error_handler.php: 28: (error message)

Exception-throwing Caller Error Handler

The example uses the following symbols

1
2
use function Korowai\Lib\Context\with;
use function Korowai\Lib\Error\callerExceptionErrorHandler;

We’re now going to implement a function which triggers an error, but blames its caller for this error. This may be easily done with the CallerExceptionErrorHandler class.

1
2
3
4
5
6
7
function trigger()
{
    with(callerExceptionErrorHandler(\ErrorException::class))(function ($eh) {
        printf("trigger_error() called at: %s: %d\n", basename(__file__), __line__ + 1);
        @trigger_error("error message");
    });
}

Finally, we test our function with the following code

1
2
3
4
5
6
7
try {
    printf("trigger() called at: %s: %d\n", basename(__file__), __line__ + 1);
    trigger();
} catch (\ErrorException $e) {
    printf("error occured at %s: %d: (%s)\n", basename($e->getFile()), $e->getLine(), $e->getMessage());
    exit(1);
}

The outputs from the above example are

  • stdout:
1
2
3
trigger() called at: caller_error_thrower.php: 21
trigger_error() called at: caller_error_thrower.php: 13
error occured at caller_error_thrower.php: 21: (error message)