Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Exception Laravel Package

phine/exception

phine/exception is an improved exception handler for Laravel that replaces the default error pages with clearer, more useful output, including richer stack traces and context to help you diagnose and fix failures faster during development.

View on GitHub
Deep Wiki
Context7

Getting Started

Prerequisites. The library is PHP 5.3-era: namespaces, no scalar type hints, no \Throwable. It targets a pre-PHP-7 world, so treat it as legacy-compatible code, not modern code.

Install. The repo is archived, so treat packagist availability as unreliable — pin explicitly and commit your composer.lock, or vendor it:

composer require phine/exception:^1.0
# if it 404s, add a VCS repository entry pointing at the GitHub repo and require a dev-* version

If you vendor it by hand, register the autoloader manually — the original layout is PSR-0 (src/Phine/Exception/*.php), not PSR-4.

Where to look first.

  1. README.md — expect it to be thin; do not trust it to be complete.
  2. src/Phine/Exception/Exception.php — the base class. Read the constructor signature carefully; that's the whole API surface you'll use 95% of the time.
  3. src/Phine/Exception/ContextException.php (if present) — the part that makes the package worth a look at all: an exception that carries structured data alongside the message.
  4. tests/ — with 11 stars and an archived README, the test suite is the documentation.

First use case. You have scattered throw new \RuntimeException('User ' . $id . ' not found') calls and your logs are unstructured strings. Replace the worst offender with a context-carrying exception so a logger can pull machine-readable fields:

use Phine\Exception\Exception;

throw new Exception(
    'User ":id" could not be loaded from ":resource".',
    array(':id' => $id, ':resource' => $resource)
);

Then at your boundary:

catch (Exception $e) {
    $logger->error($e->getMessage(), $e->getContext() + array('exception' => $e));
}

That's the entire value proposition: a message template plus a context bag, in one object.

Implementation Patterns

Template + context at the throw site. The intended flow is: interpolate user-facing/log-facing values into a readable template, keep the raw values in an array. This decouples "what the message says" from "what the code needs to know" — the message stays human-readable, the context stays machine-queryable.

Wrap and rethrow per layer. Add context as the exception crosses architectural boundaries instead of reconstructing the message:

try {
    $this->db->insert($row);
} catch (\PDOException $e) {
    throw new Exception('Failed to persist ":entity".', array(':entity' => 'user'), 0, $e);
}

getPrevious() is the only debugging aid you get for free, so always thread $e through — losing the previous exception in an archived, unmaintained library is how you spend an afternoon on a stack trace that points at the wrong line.

Domain subclasses. The cheapest integration is one subclass per failure category. Keep the constructor compatible with the base class so callers don't need to know which one they're throwing:

class UserNotFoundException extends Exception {}

Catch by category at the top (catch (UserNotFoundException $e)) and let everything else fall through to your global handler for a 500.

Logging adapter. Write one function that converts any Phine\Exception\Exception into a PSR-3 context array. Every log call then goes through it, so you can't forget fields and you get consistent log structure for free.

HTTP boundary. Map exception class → status code in a single table (validation → 422, not-found → 404, everything else → 500) and dump getContext() into a details object. Never echo getMessage() verbatim to a client if the template interpolates SQL, file paths, or IDs.

Assertions in tests. Assert on $e->getContext() rather than expectExceptionMessage(). Message strings are the part most likely to get reworded; the context keys are the contract.

Gotchas and Tips

  • Archived means frozen. No PHP 8.x fixes. catch (\Exception $e) will not catch \Error/TypeError on PHP 7+, so your global handler needs a separate \Throwable branch. Test on your actual runtime before committing.
  • Constructor argument order is the #1 footgun. Confirm whether it's ($message, array $context, $code, $previous) or ($message, $code, $previous, $context). Passing an exception as the third argument when the library expects an int $code produces a silent 0 in PHP 5 and a TypeError in PHP 7+. Read the signature, don't guess.
  • Placeholder syntax must match the formatter. If the library uses strtr() with :key placeholders, your array keys need the colon (':id', not 'id'). If it uses vsprintf(), they must not. Get this wrong and you get literal :id in production logs with no warning — missing keys are typically left untouched rather than throwing.
  • No "missing context" validation. There is generally no guard that every placeholder in the template has a matching key. Add a dev-mode assertion or a lint step if you use templates heavily; a typo'd placeholder is invisible otherwise.
  • Context must be serializable. If exceptions cross a queue, a session, or a multi-process logger, arrays of scalars survive; objects, closures, PDO handles, and resources do not. Sanitize before throwing, not before logging — the throw site is where you still know what's safe.
  • Don't dump the world into context. Full request bodies and raw SQL are tempting and turn your log storage into a liability (secrets, PII, disk). Pass identifiers and redact at the throw site.
  • Namespace collision. You'll constantly have both \Exception and Phine\Exception\Exception in scope. Always alias: use Phine\Exception\Exception as PhineException;.
  • Debugging tips. Enable zend.exception_ignore_args=0 (PHP 7.4+) so traces show constructor arguments — you'll need them to reconstruct context when a log line is truncated. And var_export($e->getContext(), true) at the catch site beats a breakpoint for async/CLI paths.
  • Extension points are few, by design. Realistically only three: subclassing for domain categories, overriding __toString() if you need a different serialization, and supplying your own formatter if you want a different placeholder syntax. If you need more than that, the package is under-serving you.
  • Verdict for the day-to-day: the concept (message + context) is sound and PSR-3 already accepts a context array, so you can get 90% of the benefit with a 20-line base exception class that you control and that supports \Throwable. Adopt this package only if it's already in a legacy tree you're maintaining; otherwise copy the pattern, not the dependency.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core