Validation rule
Rules\Redeemable validates a coupon-code form field and reports a precise, translatable message for the first failing reason — no need to catch six exceptions:
use RoundlyConsulting\Coupons\Rules\Redeemable;
$request->validate([
'code' => ['required', 'string', new Redeemable(cartTotal: $cartTotal, redeemer: $request->user())],
]);- Both arguments are optional: omit cartTotal to skip the currency and minimum-spend checks, omit redeemer to skip the per-redeemer cap.
- Empty, blank or non-string input and unknown codes fail with the not_found message. Codes match case-insensitively, so summer passes for SUMMER.
- The rule never mutates anything — usage is only incremented by a redemption.
- It asks Coupons::check() — the same checks, in the same order, as redemption and isRedeemableBy() — so they never disagree.
Messages
Messages live under the coupons::messages namespace; :code is replaced with the coupon code. The package ships English:
| Key (coupons::messages.) | Default (en) |
|---|---|
not_found | The coupon ":code" does not exist. |
currency_mismatch | This coupon cannot be used in the selected currency. |
minimum_spend_not_met | Your total does not meet this coupon’s minimum spend. |
expired | This coupon is no longer available. |
at_max_usage | This coupon has reached its usage limit. |
already_redeemed | You have already used this coupon. |
type.fixed.label / .description | Fixed amount / Subtracts a fixed amount from the price. |
type.percentage.label / .description | Percentage / Subtracts a percentage of the price. |
type.free_shipping.label / .description | Free shipping / Marks the order for free shipping. |
Translating
Publish the strings with the coupons-translations tag to reword them, or add a file for another locale under lang/vendor/coupons. For example, Slovak:
// lang/vendor/coupons/sk/messages.php
return [
'not_found' => 'Kupón „:code“ neexistuje.',
'currency_mismatch' => 'Tento kupón nie je možné použiť vo zvolenej mene.',
'minimum_spend_not_met' => 'Hodnota objednávky nedosahuje minimálnu sumu pre tento kupón.',
'expired' => 'Tento kupón už nie je platný.',
'at_max_usage' => 'Tento kupón dosiahol limit použití.',
'already_redeemed' => 'Tento kupón ste už použili.',
];The rule follows the application locale, so the same form shows the Slovak message once the locale is sk.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.