decodelabs/exceptional

Better Exceptions for PHP

v0.3.3 2022-03-09 16:37 UTC

This package is auto-updated.

Last update: 2022-08-10 11:45:49 UTC


README

PHP from Packagist Latest Version Total Downloads GitHub Workflow Status PHPStan License

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

Install via Composer:

composer require decodelabs/exceptional

PHP version

Please note, the final v1 releases of all Decode Labs libraries will target PHP8 or above.

Current support for earlier versions of PHP will be phased out in the coming months.

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('My message', [
    'code' => 1234,
    'http' => 501
]);

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

// 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

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('A bad thing happened', [
            'customData' => 'My custom info'
        ]);
    }
}

Other information