graham-campbell/result-type
Result Type is a PHP implementation of the result type, maintained by Graham Campbell. It offers a clean way to represent success or failure values instead of exceptions. Install via Composer with graham-campbell/result-type ^1.1; requires PHP 7.2.5-8.6. MIT licensed.
Result at the service layer is a lever for reducing "unhandled exception" incidents and improving mean time to diagnose failures. That maps directly to reliability OKRs and on-call toil reduction, and gives the PM a measurable claim (incidents in the target module, time-to-diagnose) rather than a stylistic one.Result values.Consider it when:
Result<T, E> and adapted at the edges.Result and Result→HTTP response.Result values in CI. Without that gate, the convention erodes within two sprints.Look elsewhere (or say no) when:
Result boundary. Mixed paradigms in one call stack produce confusing traces and inconsistent error contracts — strictly worse than the status quo.Result across queues, caches, or API responses, or relying on it as a "no-throw" guarantee. PHP lacks exhaustive matching and structural equality (new Ok(1) === new Ok(1) is false), so a carelessly unwrapped error becomes exactly the runtime failure the pattern exists to prevent.phpoption (≥1.10 in v1.2.0). Pin and audit the lock file rather than treating this as zero-dependency.For executives — the one-paragraph version:
We're proposing a small, reversible pilot, not a platform mandate. Laravel handles unexpected failures well, but it treats expected failures — a declined card, a rejected partner API call — the same as bugs. A result type lets those code paths return an explicit success-or-failure value that must be handled, which makes failure behavior visible in code review and easier to diagnose in production. The package is free, MIT-licensed, tiny, adds no infrastructure, and can be forked in an afternoon if we ever needed to. We'd run it for one quarter in one domain with one owner, measure incident rate and time-to-diagnose, and decide on data. Cost: roughly one engineer's part-time effort for a quarter, plus a one-page convention doc and a CI check. Risk: the main one isn't the software — it's that the pattern spreads informally and creates a second, competing way of handling errors.
For engineering leadership — why it's safe to try:
composer require; no service provider, no config, no migrations, no runtime hooks. Removal is equally cheap.Result lives inside the service layer. Controllers, FormRequests, middleware, jobs, and Eloquent keep speaking exceptions. We build both adapters (Result→HTTP, Result→exception) on day one so the boundary is real and enforced, not aspirational.Result across queues, caches, or API responses — convert to a DTO, enum, or exception at the edge. This is the most common design mistake with these types and our convention doc will say so explicitly.Ok and Err) get tests, not just happy paths.For the pilot team — the working agreement (pitch this as the guardrails that make it work):
Result never crosses the service boundary.The headline to lead with: this is a conditional yes to a bounded experiment, not a vote for a new house style. The cheap install is the least interesting part; the thing we're actually buying is a clearer, measurable error contract in one revenue-relevant domain — and the discipline to keep it there.
How can I help you explore Laravel packages today?