PHPackages                             jooservices/exceptions - 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. [PSR &amp; Standards](/categories/psr-standards)
4. /
5. jooservices/exceptions

ActiveLibrary[PSR &amp; Standards](/categories/psr-standards)

jooservices/exceptions
======================

Shared exception contracts and base classes for the JOOservices ecosystem.

v0.5.0(4d ago)0383↑2900%1MITPHP ^8.5

Since Jul 19Compare

[ Source](https://github.com/jooservices/exceptions)[ Packagist](https://packagist.org/packages/jooservices/exceptions)[ RSS](/packages/jooservices-exceptions/feed)WikiDiscussions Synced today

READMEChangelog (1)Dependencies (6)Versions (3)Used By (1)

JOOservices Exceptions Library
==============================

[](#jooservices-exceptions-library)

[![CI](https://github.com/jooservices/exceptions/actions/workflows/ci.yml/badge.svg)](https://github.com/jooservices/exceptions/actions/workflows/ci.yml)[![PHP Version](https://camo.githubusercontent.com/2788132aa1e54031a6c94edcbf8688566d3e18cb5492cd1766836f74a24b27b5/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e352532422d626c75652e737667)](https://www.php.net/)[![License: MIT](https://camo.githubusercontent.com/fdf2982b9f5d7489dcf44570e714e3a15fce6253e0cc6b5aa61a075aac2ff71b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f772e737667)](LICENSE)[![Packagist Version](https://camo.githubusercontent.com/d4deecfa575ffe9e2f86276b81027058cead89e7b19261f5262a7155293add08/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6a6f6f73657276696365732f657863657074696f6e73)](https://packagist.org/packages/jooservices/exceptions)

The **JOOservices Exceptions Library** is a PHP 8.5+ foundational library providing shared exception contracts, base exception classes, and structured context utilities across the JOOservices package ecosystem.

Package name: `jooservices/exceptions`

Install
-------

[](#install)

```
composer require jooservices/exceptions
```

Core Features
-------------

[](#core-features)

- **Ecosystem-Wide Catching**: Provide a root interface marker `JOOExceptionInterface` to catch any exception thrown within the JOOservices ecosystem.
- **SPL Class Semantics Preservation**: Provide separate `AbstractJOORuntimeException` and `AbstractJOOLogicException` abstract bases to preserve standard PHP SPL hierarchy.
- **Structured Diagnostic Context**: Enable context-rich logging and troubleshooting using `ContextAwareExceptionInterface` and `ExceptionContext`.
- **Sensitive Data Redaction**: Intercept and mask confidential context keys at the application boundary via `ContextRedactorInterface`.
- **Framework Decoupled**: Zero external runtime dependencies. Completely agnostic and safe to use in pure PHP libraries and framework packages alike.

Basic Usage
-----------

[](#basic-usage)

### Catching Ecosystem Exceptions

[](#catching-ecosystem-exceptions)

Catch any exception thrown by a JOOservices library:

```
use JOOservices\Exceptions\Contracts\JOOExceptionInterface;

try {
    $dto = UserDto::from($input);
} catch (JOOExceptionInterface $e) {
    // Handles any exception implementing JOOExceptionInterface
    $logger->error($e->getMessage());
}
```

### Declaring base exceptions

[](#declaring-base-exceptions)

Define package-level base exceptions using the appropriate base class:

```
use JOOservices\Exceptions\Base\AbstractJOORuntimeException;

abstract class ClientException extends AbstractJOORuntimeException {}
```

Context-Aware Exceptions
------------------------

[](#context-aware-exceptions)

For exceptions that need to carry structured diagnostic data (like fields, paths, or resource keys):

```
use JOOservices\Exceptions\Base\AbstractContextAwareException;

final class HydrationException extends AbstractContextAwareException
{
    public static function forField(string $path, string $expectedType): self
    {
        return (new self("Hydration failed for field '{$path}'"))
            ->withContext([
                'path' => $path,
                'expectedType' => $expectedType,
            ]);
    }
}
```

### Retrieving and Logging Context

[](#retrieving-and-logging-context)

```
try {
    throw HydrationException::forField('user.email', 'string');
} catch (ContextAwareExceptionInterface $e) {
    $logger->error($e->getMessage(), $e->getContext());
    // Context: ['path' => 'user.email', 'expectedType' => 'string']
}
```

Security &amp; Context Redaction
--------------------------------

[](#security--context-redaction)

To prevent sensitive keys (like passwords, keys, or credentials) from showing up in log systems, register a global redactor at application bootstrap:

```
use JOOservices\Exceptions\Base\AbstractContextAwareException;
use JOOservices\Exceptions\Contracts\ContextRedactorInterface;

AbstractContextAwareException::setRedactor(new class implements ContextRedactorInterface {
    private const SENSITIVE = ['password', 'secret', 'token', 'authorization'];

    public function redact(array $context): array
    {
        return array_map(
            fn ($key, $value) => in_array(strtolower($key), self::SENSITIVE, true) ? '[REDACTED]' : $value,
            array_keys($context),
            array_values($context),
        );
    }
});
```

Now, any exception extending `AbstractContextAwareException` will have its context keys masked when calling `getContext()`.

Trait Integration
-----------------

[](#trait-integration)

If an exception class cannot inherit from `AbstractContextAwareException` because it already inherits from a third-party class:

```
use JOOservices\Exceptions\Concerns\HasExceptionContext;
use JOOservices\Exceptions\Contracts\ContextAwareExceptionInterface;

class GuzzleWrappedException extends GuzzleException implements ContextAwareExceptionInterface
{
    use HasExceptionContext;

    public function __construct(string $message, int $code = 0, ?\Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
        $this->initContext();
    }
}
```

Verification
------------

[](#verification)

Run test suites and style linters:

```
composer check
```

###  Health Score

44

—

FairBetter than 90% of packages

Maintenance99

Actively maintained with recent releases

Popularity18

Limited adoption so far

Community5

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

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

Unknown

Total

1

Last Release

4d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/142772948?v=4)[JOOservices Ltd](/maintainers/jooservices)[@jooservices](https://github.com/jooservices)

---

Tags

phpcontractsexceptionsphp85context-awareJOOservicesbase-exception

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/jooservices-exceptions/health.svg)

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

PHPackages © 2026

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