PHPackages                             binafy/laravel-discount - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. binafy/laravel-discount

ActiveLibrary[Framework](/categories/framework)

binafy/laravel-discount
=======================

The Laravel-Discount is a Laravel package designed to handle discounts in your application effortlessly

v1.0.0(1mo ago)255MITPHP ^8.1

Since Jul 7Compare

[ Source](https://github.com/binafy/laravel-discount)[ Packagist](https://packagist.org/packages/binafy/laravel-discount)[ RSS](/packages/binafy-laravel-discount/feed)WikiDiscussions Synced 1w ago

READMEChangelog (1)Dependencies (4)Versions (3)Used By (0)

Laravel Discount
================

[](#laravel-discount)

[![laravel-discount](https://camo.githubusercontent.com/5edfe3fab1441ae9e551d2430299c871fa9c89e5c911622b74e812101018c83a/68747470733a2f2f62616e6e6572732e6265796f6e64636f2e64652f4c61726176656c253230446973636f756e742e706e673f7468656d653d6c69676874267061636b6167654d616e616765723d636f6d706f7365722b72657175697265267061636b6167654e616d653d62696e6166792532466c61726176656c2d646973636f756e74267061747465726e3d6b697769267374796c653d7374796c655f31266465736372697074696f6e3d48616e646c652b646973636f756e74732b696e2b796f75722b6170706c69636174696f6e2b6566666f72746c6573736c79266d643d312673686f7757617465726d61726b3d3026666f6e7453697a653d313235707826696d616765733d68747470732533412532462532466c61726176656c2e636f6d253246696d672532466c6f676f6d61726b2e6d696e2e737667)](https://camo.githubusercontent.com/5edfe3fab1441ae9e551d2430299c871fa9c89e5c911622b74e812101018c83a/68747470733a2f2f62616e6e6572732e6265796f6e64636f2e64652f4c61726176656c253230446973636f756e742e706e673f7468656d653d6c69676874267061636b6167654d616e616765723d636f6d706f7365722b72657175697265267061636b6167654e616d653d62696e6166792532466c61726176656c2d646973636f756e74267061747465726e3d6b697769267374796c653d7374796c655f31266465736372697074696f6e3d48616e646c652b646973636f756e74732b696e2b796f75722b6170706c69636174696f6e2b6566666f72746c6573736c79266d643d312673686f7757617465726d61726b3d3026666f6e7453697a653d313235707826696d616765733d68747470732533412532462532466c61726176656c2e636f6d253246696d672532466c6f676f6d61726b2e6d696e2e737667)

[![PHP Version Require](https://camo.githubusercontent.com/23ca64391810bba25e649a1ae732aa0babefee8958c1fc205d523d44174e9823/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646570656e64656e63792d762f62696e6166792f6c61726176656c2d646973636f756e742f706870)](https://packagist.org/packages/binafy/laravel-discount)[![Latest Stable Version](https://camo.githubusercontent.com/ed19a8eb203688ace7f4d670455704c4800e6eb5b4594ca492a27cf8eb2fef50/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f62696e6166792f6c61726176656c2d646973636f756e742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/binafy/laravel-discount)[![Total Downloads](https://camo.githubusercontent.com/9772d0f8ce98799c58236d5c38a0ac4b2ded93167856a95aedc62512fc6179c5/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f62696e6166792f6c61726176656c2d646973636f756e742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/binafy/laravel-discount)[![License](https://camo.githubusercontent.com/63cbfb57d563723d4cbd59cc2adf941ff6590a0c36e46a661ae0170d4dcbe7ea/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f62696e6166792f6c61726176656c2d646973636f756e74)](https://packagist.org/packages/binafy/laravel-discount)[![Passed Tests](https://github.com/binafy/laravel-discount/actions/workflows/run-tests.yml/badge.svg)](https://github.com/binafy/laravel-discount/actions/workflows/run-tests.yml)[![Ask DeepWiki](https://camo.githubusercontent.com/0f5ae213ac378635adeb5d7f13cef055ad2f7d9a47b36de7b1c67dbe09f609ca/68747470733a2f2f6465657077696b692e636f6d2f62616467652e737667)](https://deepwiki.com/binafy/laravel-discount)

The `Laravel-Discount` is a Laravel package designed to handle discounts in your application effortlessly. This package provides a comprehensive and flexible solution to apply various discount strategies, making it easy to integrate promotional offers, seasonal sales, and other discount-related functionalities into your Laravel project.

Features
--------

[](#features)

- Percentage Discounts: Apply percentage-based discounts to your products or services.
- Fixed Amount Discounts: Deduct a fixed amount from the total cost.
- Conditional Discounts: Set conditions for discounts, such as minimum order value or specific product categories.
- Discount Codes: Generate and manage discount codes for your customers.
- Expiry Dates: Set expiration dates for discounts to create time-limited offers.
- Usage Limits: Restrict the number of times a discount can be used.
- Stackable Discounts: Allow multiple discounts to be applied simultaneously or restrict stacking.
- Support [Laravel Cart](https://github.com/binafy/laravel-cart)
- Detailed Documentation: Comprehensive guides and examples to help you get started quickly.

---

Table of Contents
-----------------

[](#table-of-contents)

- [Requirements](#requirements)
- [Installation](#installation)
- [Publish Config &amp; Migrations](#publish-config--migrations)
- [Usage](#usage)
    - [Create a Discount](#create-a-discount)
        - [Percentage Discount](#percentage-discount)
        - [Fixed Amount Discount](#fixed-amount-discount)
        - [Maximum Discount Amount](#maximum-discount-amount)
    - [Apply a Discount](#apply-a-discount)
    - [Discount Codes](#discount-codes)
        - [Generate Codes](#generate-codes)
        - [Apply by Code](#apply-by-code)
    - [Expiry Dates &amp; Time Windows](#expiry-dates--time-windows)
    - [Usage Limits](#usage-limits)
        - [Redeeming](#redeeming)
        - [Guest Discounts](#guest-discounts)
    - [Conditional Discounts](#conditional-discounts)
        - [Minimum Order Value](#minimum-order-value)
        - [Attach Discounts to Models](#attach-discounts-to-models)
    - [Stackable Discounts](#stackable-discounts)
    - [Form Request Validation](#form-request-validation)
    - [Validation &amp; Exceptions](#validation--exceptions)
    - [Events](#events)
    - [Laravel Cart Integration](#laravel-cart-integration)
    - [Artisan Commands](#artisan-commands)
- [Testing](#testing)
- [Contributors](#contributors)
- [Security](#security)
- [License](#license)

Requirements
------------

[](#requirements)

- PHP 8.1 or higher
- Laravel 9.0 or higher

Installation
------------

[](#installation)

Install the package with Composer:

```
composer require binafy/laravel-discount
```

The service provider is registered automatically. Run the migrations to create the `discounts`, `discount_usages`, and `discountables` tables:

```
php artisan migrate
```

Publish Config &amp; Migrations
-------------------------------

[](#publish-config--migrations)

Publishing is optional — the package works out of the box. Publish the config to customize table names, the user model, or code generation defaults:

```
php artisan vendor:publish --tag="laravel-discount-config"
```

Publish the migrations if you want to change the table structure before migrating:

```
php artisan vendor:publish --tag="laravel-discount-migrations"
```

Usage
-----

[](#usage)

### Create a Discount

[](#create-a-discount)

`Binafy\LaravelDiscount\Models\Discount` is a regular Eloquent model.

#### Percentage Discount

[](#percentage-discount)

```
use Binafy\LaravelDiscount\Enums\DiscountType;
use Binafy\LaravelDiscount\Models\Discount;

$discount = Discount::query()->create([
    'name' => 'Summer Sale',
    'type' => DiscountType::Percentage,
    'value' => 20, // 20%
]);
```

#### Fixed Amount Discount

[](#fixed-amount-discount)

```
$discount = Discount::query()->create([
    'name' => 'Ten dollars off',
    'type' => DiscountType::Fixed,
    'value' => 10, // deducts 10 from the total
]);
```

> A fixed discount never exceeds the amount it is applied to, so the payable amount can never go below zero.

#### Maximum Discount Amount

[](#maximum-discount-amount)

Cap how much a discount can deduct — "20% off, up to 100":

```
$discount = Discount::query()->create([
    'code' => 'SAVE20',
    'type' => DiscountType::Percentage,
    'value' => 20,
    'max_discount_amount' => 100,
]);

LaravelDiscount::apply($discount, 300)->discountAmount;  // 60.0  (20% of 300)
LaravelDiscount::apply($discount, 1000)->discountAmount; // 100.0 (capped)
```

### Apply a Discount

[](#apply-a-discount)

Use the `LaravelDiscount` facade to apply a discount to an amount. It validates the discount first and returns a `DiscountResult`:

```
use Binafy\LaravelDiscount\Facades\LaravelDiscount;

$result = LaravelDiscount::apply($discount, 200);

$result->originalAmount;   // 200.0
$result->discountAmount;   // 40.0
$result->payableAmount();  // 160.0
$result->discounts;        // Collection of the applied discounts
```

To check a discount without throwing exceptions:

```
LaravelDiscount::isValid($discount, orderAmount: 200, user: $user); // true|false
```

### Discount Codes

[](#discount-codes)

A discount with a `code` acts as a coupon; a discount without one is an automatic discount.

```
$discount = Discount::query()->create([
    'code' => 'WELCOME10',
    'type' => DiscountType::Percentage,
    'value' => 10,
]);
```

#### Generate Codes

[](#generate-codes)

Generate cryptographically random, unique codes (ambiguous characters like `0/O` and `1/I` are excluded by default):

```
LaravelDiscount::generateCode();              // "8FJ2K9QW"
LaravelDiscount::generateCode('SUMMER');      // "SUMMER-8FJ2K9QW"
LaravelDiscount::generateCodes(100, 'VIP');   // Collection of 100 unique codes
```

Customize the length, character set, prefix, and separator in `config/laravel-discount.php` under the `codes` key.

#### Apply by Code

[](#apply-by-code)

```
$result = LaravelDiscount::applyCode('WELCOME10', 200, $user);
```

If the code does not exist, a `DiscountNotFoundException` is thrown. You can also look a discount up yourself:

```
$discount = LaravelDiscount::findByCode('WELCOME10');
```

### Expiry Dates &amp; Time Windows

[](#expiry-dates--time-windows)

Give a discount a start date, an expiry date, or both to create time-limited offers:

```
$discount = Discount::query()->create([
    'code' => 'BLACK-FRIDAY',
    'type' => DiscountType::Percentage,
    'value' => 30,
    'starts_at' => now()->startOfDay(),
    'expires_at' => now()->addDays(3),
]);
```

- Before `starts_at`, applying throws `DiscountNotStartedException`.
- After `expires_at`, applying throws `DiscountExpiredException` (and dispatches the `DiscountExpired` event).
- Query only the currently applicable discounts with the `valid()` scope:

```
Discount::query()->valid()->get();
```

### Usage Limits

[](#usage-limits)

Limit how many times a discount can be used — in total and per user:

```
$discount = Discount::query()->create([
    'code' => 'FIRST-100',
    'type' => DiscountType::Fixed,
    'value' => 15,
    'usage_limit' => 100,        // first 100 redemptions only
    'usage_limit_per_user' => 1, // once per user
]);
```

#### Redeeming

[](#redeeming)

When an order is finalized, record the redemption. This creates a `DiscountUsage` row and increments the `used_count` counter atomically — the limit check happens inside the update query, so concurrent requests can never exceed the limit:

```
LaravelDiscount::redeem($discount, $user, $result->discountAmount);
```

When the limit is exhausted, `DiscountUsageLimitReachedException` is thrown.

#### Guest Discounts

[](#guest-discounts)

Guests (not-logged-in visitors) can use discounts too. Pass a session id instead of a user, and the per-user limit is enforced per session:

```
$result = LaravelDiscount::applyCode('GUEST10', $total, sessionId: session()->getId());

LaravelDiscount::redeem($discount, amount: $result->discountAmount, sessionId: session()->getId());
```

The `discount_usages.user_id` column is nullable — guest redemptions store the `session_id` instead.

### Conditional Discounts

[](#conditional-discounts)

#### Minimum Order Value

[](#minimum-order-value)

```
$discount = Discount::query()->create([
    'code' => 'BIG-SPENDER',
    'type' => DiscountType::Percentage,
    'value' => 15,
    'min_order_value' => 500,
]);

LaravelDiscount::applyCode('BIG-SPENDER', 300); // throws MinimumOrderValueException
LaravelDiscount::applyCode('BIG-SPENDER', 800); // OK
```

The `conditions` JSON column is also available for storing your own arbitrary condition data.

#### Attach Discounts to Models

[](#attach-discounts-to-models)

Add the `HasDiscounts` trait to any model (products, categories, ...) to make it discountable:

```
use Binafy\LaravelDiscount\Traits\HasDiscounts;

class Product extends Model
{
    use HasDiscounts;
}
```

```
// Attach and query
$product->discounts()->attach($discount);
$product->validDiscounts();       // only the currently applicable ones
$product->hasDiscount('TECH10');  // by code or by model instance

// Apply all attached valid discounts to a price (stacking rules included)
$result = $product->applyDiscounts($product->price);
$result->payableAmount();
```

### Stackable Discounts

[](#stackable-discounts)

Mark a discount with `is_stackable => true` to allow it to combine with other stackable discounts. When you apply multiple discounts, the package resolves stacking automatically:

- Stackable discounts are combined (their total never exceeds the amount).
- Non-stackable discounts compete alone.
- Whichever saves the customer the most wins.
- Invalid discounts are silently skipped.

```
$result = LaravelDiscount::applyMany([$tenPercent, $tenFixed, $bigSolo], 100);

$result->discounts;       // the discounts that were actually applied
$result->discountAmount;  // the winning total
```

### Form Request Validation

[](#form-request-validation)

Validate a submitted coupon code with the `ValidDiscountCode` rule. It checks that the code exists and is currently applicable, and the error message states the exact reason (not found, expired, usage limit reached, below minimum order, ...):

```
use Binafy\LaravelDiscount\Rules\ValidDiscountCode;

public function rules(): array
{
    return [
        'code' => ['required', new ValidDiscountCode(
            orderAmount: $this->cartTotal(),
            user: $this->user(),
        )],
    ];
}
```

For guests, pass a session id instead of a user:

```
'code' => ['required', new ValidDiscountCode($total, sessionId: session()->getId())],
```

### Validation &amp; Exceptions

[](#validation--exceptions)

Every failure case has its own exception, all extending `Binafy\LaravelDiscount\Exceptions\DiscountException`:

ExceptionThrown when`DiscountNotFoundException`The given code does not exist`DiscountNotActiveException`The discount is disabled (`is_active = false`)`DiscountNotStartedException``starts_at` is in the future`DiscountExpiredException``expires_at` is in the past`DiscountUsageLimitReachedException`The total or per-user usage limit is reached`MinimumOrderValueException`The order total is below `min_order_value`Each exception carries the discount that failed, so you can handle every case separately:

```
use Binafy\LaravelDiscount\Exceptions\DiscountException;
use Binafy\LaravelDiscount\Exceptions\DiscountExpiredException;

try {
    $result = LaravelDiscount::applyCode($code, $total, $user);
} catch (DiscountExpiredException $e) {
    return back()->withErrors("Code {$e->getDiscount()->code} has expired.");
} catch (DiscountException $e) {
    return back()->withErrors($e->getMessage());
}
```

### Events

[](#events)

EventDispatched when`DiscountApplied`One or more discounts are applied to an amount`DiscountRedeemed`A redemption is recorded (after the transaction commits)`DiscountExpired`Validation encounters an expired discount```
use Binafy\LaravelDiscount\Events\DiscountRedeemed;

Event::listen(DiscountRedeemed::class, function (DiscountRedeemed $event) {
    // $event->discount, $event->usage
});
```

### Laravel Cart Integration

[](#laravel-cart-integration)

If [binafy/laravel-cart](https://github.com/binafy/laravel-cart) is installed, the `CartDiscount` service becomes available:

```
composer require binafy/laravel-cart
```

```
use Binafy\LaravelDiscount\Integrations\LaravelCart\CartDiscount;

$cartDiscount = app(CartDiscount::class);

// Apply a code (or discount models) to the whole cart total
$result = $cartDiscount->applyToCart($cart, 'SUMMER-8FJ2K9QW');
$result->payableAmount();

// Apply a discount to a specific cart item (price × quantity)
$result = $cartDiscount->applyToItem($cartItem, $discount);

// Automatically apply the discounts attached to each item's model
// (via the HasDiscounts trait) across the whole cart
$result = $cartDiscount->applyItemDiscounts($cart);
```

The cart total is checked against `min_order_value`, and the cart's user is used for per-user usage limits automatically.

### Artisan Commands

[](#artisan-commands)

Generate unique discount codes from the command line:

```
php artisan discount:generate                    # one code
php artisan discount:generate 100 --prefix=VIP  # 100 codes like VIP-8FJ2K9QW
```

Delete expired discounts (their usage records are removed with them):

```
php artisan discount:prune            # everything already expired
php artisan discount:prune --days=30  # only discounts expired 30+ days ago
```

`discount:prune` works well as a [scheduled task](https://laravel.com/docs/scheduling):

```
Schedule::command('discount:prune --days=30')->daily();
```

Testing
-------

[](#testing)

```
composer install
./vendor/bin/pest
```

Contributors
------------

[](#contributors)

Thanks to all the people who contributed. [Contributors](https://github.com/binafy/laravel-discount/graphs/contributors).

Security
--------

[](#security)

If you discover any security-related issues, please email `binafy23@gmail.com` instead of using the issue tracker.

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE) for more information.

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance90

Actively maintained with recent releases

Popularity14

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity43

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

48d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/56315159ed0aaddaed135c51aa64d56800b7be05ead525b35a0057d18b44b40e?d=identicon)[binafy](/maintainers/binafy)

---

Tags

phpframeworklaraveleloquentlaravel-packageecommercecartshopping cartcheckoutvouchersalesmilwadbinafypromotionpricingcoupondiscountpromoofferscoupon codediscount codelaravel-discount

### Embed Badge

![Health badge](/badges/binafy-laravel-discount/health.svg)

```
[![Health](https://phpackages.com/badges/binafy-laravel-discount/health.svg)](https://phpackages.com/packages/binafy-laravel-discount)
```

###  Alternatives

[binafy/laravel-cart

Laravel Cart is a customizable package for adding shopping cart functionality to Laravel applications

40658.9k1](/packages/binafy-laravel-cart)[unopim/unopim

UnoPim Laravel PIM

10.8k2.5k](/packages/unopim-unopim)[binafy/laravel-user-monitoring

Monitor your user and all activity on your application

58731.2k](/packages/binafy-laravel-user-monitoring)[milwad/laravel-validate

The Laravel-Validate package enhanced Laravel validation capabilities with custom rules and methods for simplified and efficient validation logic.

59249.3k1](/packages/milwad-laravel-validate)[nasirkhan/laravel-starter

A CMS like modular Laravel starter project.

1.4k2.7k](/packages/nasirkhan-laravel-starter)[binafy/laravel-stub

Generate stub files easy

98187.8k21](/packages/binafy-laravel-stub)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
