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

Result Laravel Package

juststeveking/result

A lightweight Result type for PHP and Laravel. Return success or failure values instead of throwing exceptions, chain transformations, and handle errors explicitly. Supports ok/err creation, mapping, and unwrapping for clearer, safer, more testable control flow.

View on GitHub
Deep Wiki
Context7

Getting Started

Install with Composer:

composer require juststeveking/result

Start with the README quickstart, then inspect JustSteveKing\Result\ResultInterface, Result, Ok, and Err. The global helpers are autoloaded via Composer, so no service provider or config publishing is required.

First practical use case: wrap a fallible service call and handle it at the HTTP boundary.

use JustSteveKing\Result\Result;

final class FetchUserProfile
{
    public function __invoke(int $id): ResultInterface
    {
        try {
            $profile = Http::get("/users/{$id}")->throw()->json();

            return Result::ok($profile);
        } catch (Throwable $e) {
            return Result::err($e);
        }
    }
}
use function JustSteveKing\Result\result_match;

$result = app(FetchUserProfile::class)(42);

return result_match(
    $result,
    fn (array $profile) => response()->json($profile),
    fn (Throwable $e) => response()->json(['message' => $e->getMessage()], 502),
);

Use this package where failure is expected and recoverable: external API calls, file imports, third-party integrations, command workflows, and domain operations that callers should handle explicitly.

Implementation Patterns

Service/action return types. Prefer returning ResultInterface<T> from service or action methods instead of throwing for expected failures. Keep unexpected exceptions throwing so Laravel’s exception handler still reports them.

/** @return ResultInterface<Order> */
public function placeOrder(Cart $cart): ResultInterface
{
    if ($cart->isEmpty()) {
        return err(new RuntimeException('Cart is empty'));
    }

    return ok($this->orders->createFromCart($cart));
}

Controller boundary handling. Use result_match() or isOk()/isErr() in controllers, form requests, or middleware. Do not leak Result objects into JSON responses.

$result = $this->placeOrder($cart);

if ($result->isErr()) {
    return response()->json([
        'message' => $result->error()?->getMessage(),
    ], 422);
}

return OrderResource::make($result->unwrap());

Chaining workflows. Use andThen() for steps that can fail and return another Result. Use map() for pure transformations of Ok values. Use mapErr() to transform exceptions. Use orElse() for recovery.

return $this->findUser($id)
    ->andThen(fn (User $user) => $this->chargeCard($user, $amount))
    ->map(fn (Payment $payment) => $payment->receipt())
    ->orElse(fn (Throwable $e) => ok(['status' => 'pending', 'reason' => $e->getMessage()]));

Side effects and observability. Use tap() and tapErr() for logging, metrics, or audit events without changing the Result.

return $this->syncInventory()
    ->tap(fn ($count) => Log::info('Inventory synced', ['count' => $count]))
    ->tapErr(fn (Throwable $e) => report($e));

Validation and command workflows. For console commands, expect() can provide a clear failure message, while valueOr() is useful for safe defaults. For queued jobs, handle the Result inside handle() and fail the job explicitly when needed.

$result = $this->importFile($path);

$count = $result->expect('Import failed');
$this->info("Imported {$count} rows");

Static analysis. Use PHPDoc generics consistently so PHPStan/Psalm understand the Ok value type.

/** @return ResultInterface<Collection<int, User>> */
public function activeUsers(): ResultInterface
{
    // ...
}

Gotchas and Tips

  • unwrap() throws on Err. It throws JustSteveKing\Result\Exceptions\UnwrapException. Catch it at a boundary, or prefer result_match(), valueOr(), or expect().
  • error() is nullable. It returns ?Throwable; it is null for Ok results. Do not call ->getMessage() without checking isErr() or null.
  • map() does not rescue errors. It transforms Ok values only. Use mapErr() for Err values and orElse() for recovery.
  • andThen() callables must return a Result. Returning a raw value will break the chain. Wrap raw values with ok()/Result::ok().
  • Do not use Results inside database transactions without care. Returning Err does not roll back a transaction. Throw inside the transaction or explicitly roll back before returning err().
  • Do not serialize Result objects directly. Convert with unwrap(), valueOr(), or result_match() before returning responses, storing data, or queuing jobs.
  • ComparableResult is narrow. It is for equality checks on int|string Ok values only. Do not treat it as general deep equality.
  • Helpers are namespaced functions. Import them with use function JustSteveKing\Result\ok; etc. There is no facade or config to publish.
  • Use Results selectively. They are a good fit for expected, recoverable failures. Keep exceptions for programmer errors, infrastructure failures, and Laravel framework flows.
  • Type your Results. Without generics, static analysis loses track of Ok values and chained transformations become harder to verify.
  • Avoid heavy work in tap()/tapErr(). They are for side effects; keep them fast and non-mutating unless intentional.
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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package