PHPackages                             decodelabs/exceptional - 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. [Debugging &amp; Profiling](/categories/debugging)
4. /
5. decodelabs/exceptional

ActiveLibrary[Debugging &amp; Profiling](/categories/debugging)

decodelabs/exceptional
======================

Better Exceptions for PHP

v0.6.7(6mo ago)344.3k—0%20MITPHPPHP ^8.4CI passing

Since Sep 29Pushed 5mo ago2 watchersCompare

[ Source](https://github.com/decodelabs/exceptional)[ Packagist](https://packagist.org/packages/decodelabs/exceptional)[ RSS](/packages/decodelabs-exceptional/feed)WikiDiscussions develop Synced 1mo ago

READMEChangelog (10)Dependencies (4)Versions (38)Used By (20)

Exceptional
===========

[](#exceptional)

[![PHP from Packagist](https://camo.githubusercontent.com/eda36094028067cb2e808a0cf70221fd7e4aa316bdda4c5ae7eee66787d68ce2/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f6465636f64656c6162732f657863657074696f6e616c3f7374796c653d666c6174)](https://packagist.org/packages/decodelabs/exceptional)[![Latest Version](https://camo.githubusercontent.com/e0a43e9fb1037835d64d9bd43b3d49c5b4c013b5614cd71620957fbc7c1553f7/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6465636f64656c6162732f657863657074696f6e616c2e7376673f7374796c653d666c6174)](https://packagist.org/packages/decodelabs/exceptional)[![Total Downloads](https://camo.githubusercontent.com/72e33c00397a745d0007920be69aaf284066efa4faf469734718179777da6d2e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6465636f64656c6162732f657863657074696f6e616c2e7376673f7374796c653d666c6174)](https://packagist.org/packages/decodelabs/exceptional)[![GitHub Workflow Status](https://camo.githubusercontent.com/df38e7bb48411dba1f4648233d3064d4cfb2ab904456a7ebc1b53953c4cd59db/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6465636f64656c6162732f657863657074696f6e616c2f696e746567726174652e796d6c3f6272616e63683d646576656c6f70)](https://github.com/decodelabs/exceptional/actions/workflows/integrate.yml)[![PHPStan](https://camo.githubusercontent.com/e25c14ce011edabdd0fbd2e10415b41cc5d66ed11ef3e5b7edd074c5bdd35a2d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d656e61626c65642d3434434331312e7376673f6c6f6e6743616368653d74727565267374796c653d666c6174)](https://github.com/phpstan/phpstan)[![License](https://camo.githubusercontent.com/bf21ed12622758f31f2409b89c6576aade04f53ff6d3f165ce132b8d8569aadd/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6465636f64656c6162732f657863657074696f6e616c3f7374796c653d666c6174)](https://packagist.org/packages/decodelabs/exceptional)

### Better Exceptions for PHP

[](#better-exceptions-for-php)

Exceptional aims to offer a radically enhanced Exception framework that decouples the *meaning* of an Exception from the underlying *implementation* functionality.

---

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

[](#installation)

This package requires PHP 8.4 or higher.

Install via Composer:

```
composer require decodelabs/exceptional
```

Usage
-----

[](#usage)

Exceptional exceptions can be used to greatly simplify how you generate and throw errors in your code, especially if you are writing a shared library.

Pass the name of your intended exception as a static call to the Exceptional base class and have a dynamic exception class created based on the most appropriate PHP Exception class along with a set of related interfaces for easier catching.

```
use DecodeLabs\Exceptional;

// Create OutOfBoundsException
throw Exceptional::OutOfBounds('This is out of bounds');

// Implement multiple interfaces
throw Exceptional::{'NotFound,BadMethodCall'}(
    "Didn't find a thing, couldn't call the other thing"
);

// You can associate a http code too..
throw Exceptional::CompletelyMadeUpMeaning(
    message: 'My message',
    code: 1234,
    http: 501
);

// Implement already existing Exception interfaces
throw Exceptional::{'InvalidArgument,Psr\\Cache\\InvalidArgumentException'}(
    message: 'Cache items must implement Cache\\IItem',
    http: 500,
    data: $item
);

// Reference interfaces using a path style
throw Exceptional::{'../OtherNamespace/OtherInterface'}('My exception');
```

Catch an Exceptional exception in the normal way using whichever scope you require:

```
namespace MyNamespace;

try {
    throw Exceptional::{'NotFound,BadMethodCall'}(
        "Didn't find a thing, couldn't call the other thing"
    );
} catch(
    \Exception |
    \BadMethodCallException |
    Exceptional\Exception |
    Exceptional\NotFoundException |
    MyNamespace\NotFoundException |
    MyNamespace\BadMethodCallException
) {
    // All these types will catch
    dd($e);
}
```

### Traits

[](#traits)

Custom functionality can be mixed in to the generated exception automatically by defining traits at the same namespace level as any of the interfaces being implemented.

```
namespace MyLibrary;

trait BadThingExceptionTrait {

    public function getCustomData(): ?string {
        return $this->params['customData'] ?? null;
    }
}

class Thing {

    public function doAThing() {
        throw Exceptional::BadThing(
            message: 'A bad thing happened',
            data: [
                'customData' => 'My custom info'
            ]
        );
    }
}
```

Other information
-----------------

[](#other-information)

- [Rationale for Exceptional](docs/Rationale.md)
- [An explanation of how the Exceptional interface works](docs/HowItWorks.md)

###  Health Score

51

—

FairBetter than 96% of packages

Maintenance69

Regular maintenance activity

Popularity29

Limited adoption so far

Community22

Small or concentrated contributor base

Maturity73

Established project with proven stability

 Bus Factor1

Top contributor holds 100% 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 ~53 days

Recently: every ~18 days

Total

36

Last Release

199d ago

PHP version history (5 changes)v0.1.0PHP ^7.2

v0.3.0PHP ^7.2|^8.0

v0.4.0PHP ^8.0

v0.4.5PHP ^8.1

v0.5.1PHP ^8.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/8a241d64d12b3b5ee94197862ec1ec30b82ed2efa34a0cd7f4c3565a021daddd?d=identicon)[betterthanclay](/maintainers/betterthanclay)

---

Top Contributors

[![betterthanclay](https://avatars.githubusercontent.com/u/1273586?v=4)](https://github.com/betterthanclay "betterthanclay (212 commits)")

---

Tags

exception-handlingexceptionsphpexception

### Embed Badge

![Health badge](/badges/decodelabs-exceptional/health.svg)

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

###  Alternatives

[filp/whoops

php error handling for cool kids

13.2k402.4M1.4k](/packages/filp-whoops)[yireo/magento2-whoops

Magento 2 module adding Whoops error handling

102703.5k](/packages/yireo-magento2-whoops)[jolicode/gif-exception-bundle

The GhostBuster of your exception page

20596.8k](/packages/jolicode-gif-exception-bundle)[ikkez/f3-falsum

Pretty error handling for Fat-Free Framework

21145.8k3](/packages/ikkez-f3-falsum)[kuria/error

Makes handling and debugging PHP errors suck less

1920.0k2](/packages/kuria-error)[thehocinesaad/laravel-error-ai

This package adds Ask AI button to the error page.

2214.4k](/packages/thehocinesaad-laravel-error-ai)

PHPackages © 2026

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