softrules/php
SoftRules for PHP offers a lightweight way to define and evaluate soft validation rules in Laravel apps, letting you flag or score issues without hard failures.
Requirements check first. v0.3.0 is the first line of releases that tracks illuminate/* 12.x alongside 11.x. Before installing, confirm your app's PHP version and Laravel major against the composer.json constraints in the package — the dev dependencies moved from illuminate/http 11.37 → 12.8.1 over this cycle, which usually signals widened ^11.0|^12.0 support rather than a hard bump.
composer require softrules/php
Where to look first:
README.md — the package's public surface is small; the README examples are the authoritative usage contract.src/ — look for the rule classes and any service provider; that tells you whether registration is automatic (package discovery) or manual.tests/ — the test suite is the fastest way to see expected input/output shapes, especially for edge cases the README skips.composer.json require vs require-dev — this release is almost entirely require-dev (Pint, PHPStan, Rector), so the runtime footprint should be tiny.First use case: attach a rule to a FormRequest and observe the difference between a hard failure and a soft signal:
public function rules(): array
{
return [
'email' => ['required', 'email', new YourSoftRule()],
];
}
Then write one test that asserts both the "clean" and "flagged" paths before wiring it into a real endpoint.
Validation-layer integration. The natural home for this package is a FormRequest or a Validator::make() call in a controller/action. Keep soft rules in a dedicated array or a named method so they are visually separated from blocking rules — mixing them in a flat rules() array makes it easy for a future reader to assume they reject input.
Progressive rollout. Wire soft rules into a job, command, or a "dry run" branch of a queued listener before putting them in the request path. Because the package's output is advisory, you can log the result on real traffic for a week and only then decide whether to surface it to users.
Testing. The repo carries PHPUnit plus phpstan/phpstan-phpunit (now 2.0.6), so the package itself is test-first. Mirror that: use Validator::make(...)->passes() / ->fails() assertions and, where the package exposes a result object, assert on the collected messages rather than just pass/fail.
Keeping tooling in sync. The release ships laravel/pint 1.22.0 and rector/rector 2.0.11. If you vendor the package's pint.json or rector.php into your own app's config, diff them on upgrade — Pint 1.20 → 1.22 and Rector 2.0.6 → 2.0.11 both carry rule changes that can reformat untouched files.
HTTP-adjacent work. illuminate/http and guzzlehttp/guzzle 7.9.3 are both in the tree, so if your rules do any outbound lookup (DNS, deliverability, remote schema), instantiate through Laravel's HTTP client rather than raw Guzzle so Http::fake() works in tests.
This release is dependency-only. Every entry in the v0.2.13 → v0.3.0 changelog is a Dependabot bump — no features, no deprecations, no API changes are listed. Treat it as a maintenance release: composer update softrules/php is low risk, but you should still diff the package's composer.json against your lock file.
The Laravel 12 signal is the real news. illuminate/collections, support, and http climbed all the way to 12.8.1. If you were previously pinned to Laravel 11 because of this package, v0.3.0 is likely your upgrade path. Verify by running composer why-not laravel/framework ^12.0 after installing.
Don't mix illuminate majors. If your composer.lock ends up with illuminate/support 12.x but illuminate/http 11.x (possible when other packages pin narrowly), you'll get confusing type errors. Run composer show 'illuminate/*' and confirm one major across the board.
PHPStan 2.x is a breaking change for baselines. Both phpstan/phpstan (2.1.11) and the extensions moved within 2.x during this cycle. If you extend the package's static analysis config, regenerate any baseline — old ignore patterns for renamed internals will silently stop matching.
Debugging soft-rule output. If a rule "passes" but you expected a warning, check whether your validator is short-circuiting on an earlier failing rule (bail) — soft results computed after a bail never run. Log the rule's raw result before formatting it.
Extension points. Before writing your own rule, check whether the package exposes an abstract base class or a contract in src/. Subclassing the provided base is safer than implementing the raw Rule contract, because the package may add a result-normalization step between versions that a hand-rolled rule would bypass.
Pinning strategy. Given how frequently this package's dev tooling churns, consider composer require softrules/php:^0.3 rather than a wider constraint, and let Dependabot PRs reveal breaking changes in a controlled way rather than absorbing them in a routine composer update.
How can I help you explore Laravel packages today?