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

Php Assumptions Laravel Package

rskuipers/php-assumptions

PHP Assumptions is a static analysis tool that detects hidden assumptions in your code, like variables used without guarantees about their type or existence. It reports each assumption, helping you catch risky spots and improve type safety. Runs via Composer and CLI.

Deep Wiki
Context7

Getting Started

rskuipers/php-assumptions is a small, framework-agnostic library for expressing and enforcing assumptions — the invariants your code silently relies on ("this array has a id key", "this service returns a non-empty collection", "this JSON payload has an email"). Instead of a bare assert() or an ad-hoc if (...) throw, you declare the assumption in a readable, chainable way and get a consistent failure mode when reality disagrees.

Minimal steps

  1. composer require rskuipers/php-assumptions (PHP 8.x; MIT; released March 2025, so it is current).
  2. There is no service provider and no config file — it is a plain Composer package. That is the first thing to internalise: nothing is auto-wired, so you decide where the entry points live.
  3. Read the README's list of available checks first, then the exception class it throws. Those two things define your whole integration surface.
  4. Wire the exception into app/Exceptions/Handler.php (or bootstrap/app.php in Laravel 11+) if you intend to catch it — see Gotchas.

First use case

The highest-value first use is a boundary guard in a service class that receives data the framework has not fully validated: a webhook payload, a third-party API response, or a queued job's array payload. Something like:

use Rskuipers\Assumptions\Assumptions; // confirm exact namespace in the README

final class SyncInvoice
{
    public function __invoke(array $payload): Invoice
    {
        Assumptions::check($payload)
            ->hasKey('id')
            ->hasKey('customer.email')
            ->that($payload['id'])->isString();

        // ... from here on, trust the shape
    }
}

Pick exactly one such call site, run the happy path and a deliberately malformed payload, and confirm the failure is loud and points at the right line. That five-minute exercise tells you more than the docs.

Implementation Patterns

1. Guard the edges, trust the core. The idiomatic split in a Laravel app is: Form Requests / Validator for user input (they produce 422s and field-level messages), assumptions for everything else — HTTP client responses, queue payloads, config arrays, filesystem reads, cache values. Assumptions are for "this should be impossible", not "the user might have typed this".

2. Action and service classes. The natural home is the top of an invokable action or a domain service — one assumption block per public method, immediately after the signature, before any real work. This gives readers a contract and gives you a stack trace that points at the exact method that received the bad value rather than 40 lines downstream.

3. DTO / value-object hydration. When you map an array (from Http::get()->json(), a job payload, or an event) into a DTO, assert the shape once during hydration and then let the DTO carry the guarantee. This is the pattern that pays for the dependency fastest — it lets the rest of the codebase drop defensive ?? and isset() noise.

4. Jobs and console commands. Queued jobs deserialise from an array you do not control once it has been sitting on the queue. A single assumption at the top of handle() turns a confusing Undefined array key deep in a model into a named failure with the offending payload in the trace.

5. Testing against them. Because assumptions throw a dedicated exception, tests become explicit: assert the happy path returns, and assert the exception is thrown for each malformed shape. Add a small data provider of broken payloads — it doubles as documentation of what the boundary rejects.

6. Keep a helper if you use it a lot. If your call sites get verbose, wrap the facade in a project-level helper (app/Support/assume.php or a static Guard class) so the import lives in one place. This also lets you swap or remove the library later without touching dozens of files.

7. Complements static analysis, doesn't replace it. Assumptions are runtime checks. PHPStan/Larastan will not understand that a check narrows a mixed type, so you still need @param docblocks or an inline /** @var array{id: string} $payload */ after the assumption to keep analysis clean.

Gotchas and Tips

  • Do not use it to validate user input. An assumption failure is a bug or an upstream contract break, and should surface as a 500, not a 422. If you find yourself mapping assumption exceptions to validation errors, you are using the wrong tool — reach for Validator instead.
  • assert() is not the same thing. zend.assertions=-1 in production silently disables the built-in assertions, which is exactly the trap this package exists to avoid. Confirm the library always evaluates (check whether it has any environment toggling) — that is the main behavioural question worth verifying in the source.
  • Register the exception in the handler if you need a specific status. By default an uncaught package exception is a 500, which is usually correct. If you want a 400 for a specific boundary (e.g. a partner webhook), add a targeted renderable/respond branch rather than a global catch.
  • Performance in hot loops. Exception construction with a stack trace is not free. Hoisting one assumption to the top of a batch method beats asserting inside a per-row loop.
  • Autoloaded functions. If the package ships global functions via Composer's files autoload, be aware they load on every request and can collide with your own helpers. Prefer the class-based API if both exist.
  • No magic narrowing for static analysis. Follow every assumption with a docblock where the type genuinely narrows, or PHPStan will keep reporting mixed access errors and you will be tempted to sprinkle ignores.
  • Extension points are thin by design. If you need richer checks (e.g. "is a well-formed ULID", "is a non-empty Collection"), write tiny named constructors or your own helper around the package rather than forking — the library is deliberately minimal, and its 3.7 score reflects "does one thing, small surface" rather than "batteries included".
  • Pin the version and read the changelog on upgrade. With one maintainer and a small API surface, breaking changes in method names are cheap for them and expensive for you; the March 2025 release is recent enough that you should check the diff rather than trusting ^1.0 blindly.
  • Verdict: worth adding as a targeted boundary tool in a codebase with several external integrations. It is not a replacement for validation, DTOs, or static analysis, and if your app has no untrusted boundaries beyond HTTP forms, the value is marginal.
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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib