PHPackages                             mensbeam/catcher - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. mensbeam/catcher

ActiveLibrary

mensbeam/catcher
================

Catches exceptions, errors, and shutdowns

v2.1.7(11mo ago)0140↓100%MITPHPPHP &gt;=8.1

Since Dec 31Pushed 11mo ago2 watchersCompare

[ Source](https://github.com/mensbeam/Catcher)[ Packagist](https://packagist.org/packages/mensbeam/catcher)[ RSS](/packages/mensbeam-catcher/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (5)Versions (17)Used By (0)

Catcher
=======

[](#catcher)

*Catcher* is a Throwable catcher and error handling library for PHP. Error handling is accomplished using a stack-based approach.

*Catcher* uses classes called *handlers* to handle throwables sent its way. PHP is currently in a state of flux when it comes to errors. There are traditional PHP errors which are triggered in userland by using `trigger_error()` which can't be caught using `try`/`catch` and are generally a pain to work with. PHP has begun to remedy this problem by introducing the `\Error` class and its various child classes. However, a lot of functions and core aspects of the language itself continue to use legacy errors. This class attempts to make that pain point much easier by throwing fatal errors as `\Error`s. It is possible to configure *Catcher* on the fly to throw non fatal errors, allowing you to easily catch them as you would exceptions.

Requirements
------------

[](#requirements)

- PHP &gt;= 8.1
- [mensbeam/self-sealing-callable](https://code.mensbeam.com/MensBeam/SelfSealingCallable) ^1.0
- [psr/log](https://github.com/php-fig/log) ^3.0

Installation
------------

[](#installation)

```
composer require mensbeam/catcher
```

Usage
-----

[](#usage)

For most use cases this library requires no configuration and little effort to integrate into non-complex environments:

```
use MensBeam\Catcher;

$catcher = new Catcher();
```

That's it. It will automatically register Catcher as an exception, error, and shutdown handler and use `PlainTextHandler` as its sole handler. *Catcher* is fully configurable and can be configured to use one or multiple *handlers*. At present there is only one handler, the aforementioned `PlainTextHandler`. All handlers may be configured to log errors like so:

```
use MensBeam\Catcher,
    MensBeam\Logger;

$catcher = new Catcher(
    new PlainTextHandler([
        'logger' => new Logger('log'),
        'silent' => true
    ])
);
```

The example above uses [Logger](https://code.mensbeam.com/MensBeam/Logger) for its logger, but any PSR-3-compatible logger will work.

### A Note About Notices, Warnings, etc.

[](#a-note-about-notices-warnings-etc)

As described in the summary paragraph at the beginning of this document, Catcher by default converts all fatal errors to `Throwable`s and will leave warnings, notices, etc. alone. However, it can be configured to throw these too.

```
$catcher = new Catcher();
$catcher->errorHandlingMethod = Catcher::THROW_ALL_ERRORS;

try {
    trigger_error(\E_USER_WARNING, 'Ook!');
} catch (\Throwable $t) {
    echo $t->message();
}
```

Output:

```
Ook!

```

### Error Handling

[](#error-handling)

PHP by default won't allow fatal errors to be handled by error handlers. It will instead print the error and exit. However, before code execution halts any shutdown functions are run. Catcher will retrieve the last error and manually process it. This causes multiple instances of the same error to be output. Because of this Catcher alters the error reporting level by always removing `E_ERROR` from it when registering the handlers. `E_ERROR` is bitwise or'd back to the error reporting level when unregistering. If this behavior is undesirable then `E_ERROR` can be manually included back into error reporting at any time after Catcher instantiates. Keep in mind Catcher *will not* include `E_ERROR` back into the error reporting level bitmask if the error reporting level was modified after Catcher was instantiated or if the error reporting level didn't have it when Catcher registered its handlers.

Documentation
-------------

[](#documentation)

### MensBeam\\Catcher

[](#mensbeamcatcher)

This is the main class in the library. Unless you have a need to configure a handler or use multiple handlers there usually isn't a need to interact with the rest of the library at all.

```
namespace MensBeam;
use MensBeam\Catcher\Handler;

class Catcher {
    public const THROW_NO_ERRORS = 0;
    public const THROW_FATAL_ERRORS = 1;
    public const THROW_ALL_ERRORS = 2;

    public int $errorHandlingMethod = self::THROW_FATAL_ERRORS;
    public bool $preventExit = false;

    public function __construct(Handler ...$handlers);

    public function getHandlers(): array;
    public function getLastThrowable(): ?\Throwable;
    public function isRegistered(): bool;
    public function popHandler(): Handler;
    public function pushHandler(Handler ...$handlers): void;
    public function register(): bool;
    public function setHandlers(Handler ...$handlers): void;
    public function shiftHandler(): Handler;
    public function unregister(): bool;
    public function unshiftHandler(Handler ...$handlers): void;
}
```

#### Constants

[](#constants)

*THROW\_NO\_ERRORS*: When used in *errorHandlingMethod* will cause Catcher to not throw any errors.
*THROW\_FATAL\_ERRORS*: When used in *errorHandlingMethod* will cause Catcher throw only fatal errors; this is the default behavior.
*THROW\_ALL\_ERRORS*: When used in *errorHandlingMethod* will cause Catcher to throw all errors.
*NOW*: When returned within the output bitmask, it causes Catcher to have the handler immediately be invoked.
*OUTPUT*: When returned within the output bitkask, it causes the handler to output the throwable when invoked.

#### Properties

[](#properties)

*errorHandlingMethod*: Determines how errors are handled; THROW\_\* constants exist to control
*preventExit*: When set to true Catcher won't exit at all even after fatal errors or exceptions

#### MensBeam\\Catcher::getHandlers

[](#mensbeamcatchergethandlers)

Returns an array of the handlers defined for use in the Catcher instance

#### MensBeam\\Catcher::getLastThrowable

[](#mensbeamcatchergetlastthrowable)

Returns the last throwable that this instance of Catcher has handled

#### MensBeam\\Catcher::isRegistered

[](#mensbeamcatcherisregistered)

Returns whether the Catcher still is registered as a error, exception, and shutdown handler

#### MensBeam\\Catcher::popHandler

[](#mensbeamcatcherpophandler)

Pops the last handler off the stack and returns it

#### MensBeam\\Catcher::pushHandler

[](#mensbeamcatcherpushhandler)

Pushes the specified handler(s) onto the stack

#### MensBeam\\Catcher::register

[](#mensbeamcatcherregister)

Registers the Catcher instance as an error, exception, and shutdown handler. By default the constructor does this automatically, but this method exists in case `unregister` has been called.

#### MensBeam\\Catcher::setHandlers

[](#mensbeamcatchersethandlers)

Replaces the stack of handlers with those specified as parameters.

#### MensBeam\\Catcher::shiftHandler

[](#mensbeamcatchershifthandler)

Shifts the first handler off the stack of handlers and returns it.

#### MensBeam\\Catcher::unregister

[](#mensbeamcatcherunregister)

Unregisters the Catcher instance as an error, exception and shutdown handler.

#### MensBeam\\Catcher::unshiftHandler

[](#mensbeamcatcherunshifthandler)

Unshifts the specified handler(s) onto the beginning of the stack

### MensBeam\\Catcher\\Handler

[](#mensbeamcatcherhandler)

All handlers inherit from this abstract class. Since it is an abstract class meant for constructing handlers protected methods and properties will be documented here as well.

```
namespace MensBeam\Catcher;

abstract class Handler {
    public const CONTENT_TYPE = null;

    public const NON_FATAL_ERROR = \E_NOTICE | \E_USER_NOTICE | \E_WARNING | \E_COMPILE_WARNING | \E_USER_WARNING | \E_DEPRECATED | \E_USER_DEPRECATED;

    // Control constants
    public const BUBBLES = 1;
    public const EXIT = 2;
    public const LOG = 4;
    public const NOW = 8;
    public const OUTPUT = 16;

    protected ?array $lastOutputThrowable;
    protected array $outputBuffer;

    // Options
    protected int $_backtraceArgFrameLimit = 5;
    protected bool $_bubbles = true;
    protected string $_charset = 'UTF-8';
    protected bool $_forceExit = false;
    protected bool $_forceOutputNow = false;
    protected int $_httpCode = 500;
    protected ?array $_ignore = null;
    protected ?LoggerInterface $_logger = null;
    protected bool $_logWhenSilent = true;
    protected bool $_outputBacktrace = false;
    protected bool $_outputPrevious = true;
    protected bool $_outputTime = true;
    protected bool $_outputToStderr = true;
    protected bool $_silent = false;
    protected string $_timeFormat = 'Y-m-d\TH:i:s.vO';

    public function __construct(array $options = []);

    public function __invoke(): void;
    public function getLastOutputThrowable(): ?array;
    public function getOption(string $name): mixed;
    public function setOption(string $name, mixed $value): void;

    protected function buildOutputArray(ThrowableController $controller): array;
    protected function cleanOutputThrowable(array $outputThrowable): array;
    abstract protected function handleCallback(array $output): array;
    abstract protected function invokeCallback(): void;
    protected function log(\Throwable $throwable, string $message): void;
    protected function print(string $string): void;
    protected function serializeArgs(mixed $value): string;
}
```

#### Constants

[](#constants-1)

*CONTENT\_TYPE*: The mime type of the content that is output by the handler

*BUBBLES*: When returned within the output bitmask, it causes the stack loop to continue onto the next handler after handling; this is the default behavior.
*EXIT*: When returned within the output bitmask, it causes Catcher to exit after running all handlers.
*LOG*: When returned within the output bitmask, it causes Catcher to log the output to a supplied logger.
*NOW*: When returned within the output bitmask, it causes Catcher to have the handler immediately be invoked.
*OUTPUT*: When returned within the output bitkask, it causes the handler to output the throwable when invoked.

#### Properties (Protected)

[](#properties-protected)

*outputBuffer*: This is where the output arrays representing the handled throwables are stored until they are dispatched.

#### Options

[](#options)

Properties which begin with an underscore all are options. They can be set either through the constructor or via `setHandler` by name, removing the underscore at the beginning. All handlers inherit these options. Options in inherited classes should also begin with an underscore (*\_*). How to extend `Handler` will be explained further down in the document.

*backtraceArgFrameLimit*: The number of frames by which there can be arguments output with them. Defaults to *5*.
*bubbles*: If true the handler will move onto the next item in the stack of handlers. Defaults to *true*.
*charset*: The character set of the output; only used if headers weren't sent before an error occurred. No conversion is done. Defaults to *"UTF\_8"*.
*forceBreak*: When set this will force the stack loop to break after the handler has run. Defaults to *false*.
*forceExit*: When set this will force an exit after all handlers have been run. Defaults to *false*.
*forceOutputNow*: When set this will force output of the handler immediately. Defaults to *false*.
*httpCode*: The HTTP code to be sent; possible values are 200, 400-599. Defaults to *500*.
*ignore*: An array of class strings or error code bitmasks to ignore. Defaults to *null* (no ignoring).
*logger*: The PSR-3 compatible logger in which to log to. Defaults to *null* (no logging).
*logWhenSilent*: When set to true the handler will still send logs when silent. Defaults to *true*.
*outputBacktrace*: When true will output a stack trace. Defaults to *false*.
*outputPrevious*: When true will output previous throwables. Defaults to *true*.
*outputTime*: When true will output times to the output. Defaults to *true*.
*outputToStderr*: When the SAPI is cli output errors to stderr. Defaults to *true*.
*silent*: When true the handler won't output anything. Defaults to *false*.
*timeFormat*: The PHP-standard date format which to use for times in output. Defaults to *"Y-m-d\\TH:i:s.vO"*.

#### MensBeam\\Catcher\\Handler::\_\_invoke

[](#mensbeamcatcherhandler__invoke)

Outputs the stored throwable arrays in the output buffer.

#### MensBeam\\Catcher\\Handler::getLastOutputThrowable

[](#mensbeamcatcherhandlergetlastoutputthrowable)

Returns the last output throwable array handled by this handler (or null if there hasn't been one); useful when debugging

#### MensBeam\\Catcher\\Handler::getOption

[](#mensbeamcatcherhandlergetoption)

Returns the value of the provided option name

#### MensBeam\\Catcher\\Handler::handle

[](#mensbeamcatcherhandlerhandle)

Handles the provided `ThrowableController` and stores the output array in the output buffer to be dispatched later

#### MensBeam\\Catcher\\Handler::setOption

[](#mensbeamcatcherhandlersetoption)

Sets the provided option with the provided value

#### MensBeam\\Catcher\\Handler::buildOutputArray (protected)

[](#mensbeamcatcherhandlerbuildoutputarray-protected)

With a given `ThrowableController` will output an array to be stored in the output buffer

#### MensBeam\\Catcher\\Handler::cleanOutputThrowable (protected)

[](#mensbeamcatcherhandlercleanoutputthrowable-protected)

"Cleans" an output throwable -- an individual item in the output array -- by removing information that's unnecessary in the output; useful for structured data output such as JSON.

#### MensBeam\\Catcher\\Handler::handleCallback (protected)

[](#mensbeamcatcherhandlerhandlecallback-protected)

A callback method meant to be extended by inherited classes where the output array can be manipulated before storing in the output buffer

#### MensBeam\\Catcher\\Handler::invokeCallback (protected)

[](#mensbeamcatcherhandlerinvokecallback-protected)

A callback method meant to be extended by inherited classes to control how the class outputs the throwable arrays

#### MensBeam\\Catcher\\Handler::print (protected)

[](#mensbeamcatcherhandlerprint-protected)

Prints the provided string to stderr or stdout depending on how the handler is configured and which SAPI is being used.

#### MensBeam\\Catcher\\Handler::serializeArgs (protected)

[](#mensbeamcatcherhandlerserializeargs-protected)

Serializes argument arrays in stack traces; does not recurse, only showing top level arguments.

### MensBeam\\Catcher\\ThrowableController

[](#mensbeamcatcherthrowablecontroller)

We cannot require all throwables to be converted to our own classes, so this class exists as a controller to add new features to throwables for use with Catcher.

```
namespace MensBeam\Catcher;

class ThrowableController {
    public function __construct(\Throwable $throwable);

    public function getErrorType(): ?string;
    public function getFrames(int $argFrameLimit = \PHP_INT_MAX): array;
    public function getPrevious(): ?ThrowableController;
    public function getThrowable(): \Throwable;
}
```

#### MensBeam\\Catcher\\ThrowableController::getErrorType

[](#mensbeamcatcherthrowablecontrollergeterrortype)

Returns the error type of a `MensBeam\Catcher\Error`, meaning a human-friendly representation of the error code (eg: *"Fatal Error"*, *"Warning"*, *"Notice"*) or null if the throwable isn't an `Error`.

#### MensBeam\\Catcher\\ThrowableController::getFrames

[](#mensbeamcatcherthrowablecontrollergetframes)

Returns the frames for the throwable as an array with deduplication and fixes all taken care of

#### MensBeam\\Catcher\\ThrowableController::getPrevious

[](#mensbeamcatcherthrowablecontrollergetprevious)

Returns the previous `ThrowableController` if there is one

#### MensBeam\\Catcher\\ThrowableController::getThrowable

[](#mensbeamcatcherthrowablecontrollergetthrowable)

Returns the throwable controlled by this class instance

### MensBeam\\Catcher\\JSONHandler

[](#mensbeamcatcherjsonhandler)

```
namespace MensBeam\Catcher;

class JSONHandler extends Handler {
    public const CONTENT_TYPE = 'application/json';

    protected bool $_prettyPrint = true;
    protected bool $_prettyPrintWhenLogging = false;
}
```

#### Options

[](#options-1)

*prettyPrint*: If true the handler will pretty print JSON output. Defaults to *true*. *prettyPrintWhenLogging*: If true the handler will pretty print JSON output when logging. Defaults to *false*.

### MensBeam\\Catcher\\PlainTextHandler

[](#mensbeamcatcherplaintexthandler)

```
namespace MensBeam\Catcher;

class PlainTextHandler extends Handler {
    public const CONTENT_TYPE = 'text/plain';

    protected string $_timeFormat = '[H:i:s]';
}
```

#### Options

[](#options-2)

*timeFormat*: Same as in `Handler`, but the default changes to *"\[H:i:s\]"*.

###  Health Score

36

—

LowBetter than 83% of packages

Maintenance50

Moderate activity, may be stable

Popularity11

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity62

Established project with proven stability

 Bus Factor1

Top contributor holds 98.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~54 days

Recently: every ~126 days

Total

16

Last Release

359d ago

Major Versions

v1.1.0 → v2.02023-04-30

### Community

Maintainers

![](https://www.gravatar.com/avatar/c92ee740b64f961a67127263de9c7ac85b4b934fc7d0e6a397ed8b16a7f09f91?d=identicon)[JKingweb](/maintainers/JKingweb)

![](https://www.gravatar.com/avatar/fa45644fa8847647e3d12802571072bbd4f3da8d27ed03f6f8df3c3859db6f6e?d=identicon)[dustinwilson](/maintainers/dustinwilson)

---

Top Contributors

[![dustinwilson](https://avatars.githubusercontent.com/u/1885928?v=4)](https://github.com/dustinwilson "dustinwilson (65 commits)")[![JKingweb](https://avatars.githubusercontent.com/u/89590?v=4)](https://github.com/JKingweb "JKingweb (1 commits)")

---

Tags

errorerror-handlingexceptionexception-handlingshutdown

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/mensbeam-catcher/health.svg)

```
[![Health](https://phpackages.com/badges/mensbeam-catcher/health.svg)](https://phpackages.com/packages/mensbeam-catcher)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
