PHPackages                             mcjy/rule-engine - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. mcjy/rule-engine

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

mcjy/rule-engine
================

A flexible and extensible PHP promotion rule engine for shopping cart scenarios — supports discounts, tiered offers, member pricing, and more.

v1.0.1(1mo ago)00MITPHPPHP &gt;=7.4

Since Jun 13Pushed 1mo agoCompare

[ Source](https://github.com/weijunlike/rule-engine)[ Packagist](https://packagist.org/packages/mcjy/rule-engine)[ RSS](/packages/mcjy-rule-engine/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependenciesVersions (3)Used By (0)

🛒 mcjy/rule-engine
==================

[](#-mcjyrule-engine)

 [English](./README.md)｜[简体中文](./README.zh-CN.md)---

A **flexible and extensible** PHP promotion rule engine for shopping cart scenarios — supports discounts, tiered offers, member pricing, and more, implemented elegantly and maintainably.

---

📦 Installation
--------------

[](#-installation)

Install via Composer:

```
composer require mcjy/rule-engine
```

---

🚀 Usage
-------

[](#-usage)

```
use Mcjy\RuleEngine\Models\Cart;
use Mcjy\RuleEngine\Models\User;
use Mcjy\RuleEngine\PromotionEngine;
use Mcjy\RuleEngine\Rules;

// Create user (VIP)
$user = new User(vip: true);

// Create a shopping cart
$cart = new Cart();
$cart->addItem('Product A', 50, 1, ['snacks']);
$cart->addItem('Product B', 60, 1, ['clothes']);
$cart->addItem('Product C', 40, 1, ['clothes']);
$cart->addItem('Product D', 100, 1, ['promo']);
$cart->addItem('Product E', 30, 3, ['snacks']);
$cart->addItem('Product F', 200, 1, ['electronics']);

// Initialize the promotion engine
$engine = new PromotionEngine();

// Calculation modes:
//
// independent:
//   Each rule calculates the discount separately based on the original product price.
//   Discounts are aggregated at the end; intermediate results do not affect other rules.
//
// sequential:
//   Each rule continues calculating based on the previously adjusted price (discount-on-discount).
//   When a rule involves multiple products, the discount is distributed proportionally.
//
// lock:
//   Each product can only be discounted by one rule. Subsequent rules skip already-locked items.
//   Suitable for scenarios where only one promotion can apply per item (flash sales, exclusive coupons, etc.).
$engine->setMode('independent');

// Register rules
$engine->addRule(new Rules\FullDiscountRule(200, 0.9));           // 10% off over ¥200
$engine->addRule(new Rules\FullQuantityReductionRule(3, 20));     // ¥20 off when buying 3+ items
$engine->addRule(new Rules\NthItemDiscountRule(3, 0.5));          // 3rd item 50% off
$engine->addRule(new Rules\VipDiscountRule(0.95));                // VIP 5% off
$engine->addRule(new Rules\FullQuantityDiscountRule(5, 0.9));     // 10% off when buying 5+ items
$engine->addRule(new Rules\FullReductionRule(100, 20));           // ¥20 off over ¥100
$engine->addRule(new Rules\VipReductionRule(5));                  // VIP ¥5 off

// Calculate
$result = $engine->calculate($cart, $user);

// Print result
echo "\n=== Result ===\n";
echo "Original: ¥{$result['original']}\n";
echo "Discount: -¥{$result['discount']}\n";
echo "Final:    ¥{$result['final']}\n";
echo "Details:\n";
foreach ($result['details'] as $detail) {
    echo "- {$detail}\n";
}
```

---

🛠️ Built-in Rule Types
----------------------

[](#️-built-in-rule-types)

RuleDescription`FullDiscountRule`X% off when total reaches threshold (e.g. 20% off over ¥200)`FullReductionRule`¥Y off when total reaches threshold (e.g. ¥20 off over ¥100)`FullQuantityDiscountRule`X% off when buying N+ items (e.g. 10% off for 3+ items)`FullQuantityReductionRule`¥Y off when buying N+ items (e.g. ¥20 off for 3+ items)`TieredDiscountRule`Tiered % discount — highest qualifying tier applies`TieredReductionRule`Tiered fixed reduction — highest qualifying tier applies`NthItemDiscountRule`Nth item at X% off (e.g. 3rd item 50% off)`NthItemReductionRule`Nth item at a fixed special price (e.g. 3rd item ¥9.9)`VipDiscountRule`VIP users get a % discount`VipReductionRule`VIP users get a fixed reduction---

🧩 Extending with Custom Rules
-----------------------------

[](#-extending-with-custom-rules)

Implement `PromotionRuleInterface` to add your own rule:

```
use Mcjy\RuleEngine\Contracts\PromotionRuleInterface;
use Mcjy\RuleEngine\Models\Cart;
use Mcjy\RuleEngine\Models\User;
use Mcjy\RuleEngine\PromotionResult;

class MyCustomRule implements PromotionRuleInterface
{
    public function apply(Cart $cart, User $user, array $eligibleIndexes = []): PromotionResult
    {
        // Your discount logic here
    }

    public function getApplicableItems(Cart $cart): array { /* ... */ }
    public function getPriority(): int { return 1; }
    public function getApplicableTags(): array { return []; }
}
```

---

📄 License
---------

[](#-license)

MIT

###  Health Score

34

—

LowBetter than 75% of packages

Maintenance90

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity35

Early-stage or recently created project

 Bus Factor1

Top contributor holds 75% of commits — single point of failure

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 ~318 days

Total

2

Last Release

45d ago

PHP version history (2 changes)v1.0.0PHP &gt;=8.1

v1.0.1PHP &gt;=7.4

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/40715652?v=4)[weijunlike](/maintainers/weijunlike)[@weijunlike](https://github.com/weijunlike)

---

Top Contributors

[![zxc7563598](https://avatars.githubusercontent.com/u/46590942?v=4)](https://github.com/zxc7563598 "zxc7563598 (3 commits)")[![mingzhanliao](https://avatars.githubusercontent.com/u/63911596?v=4)](https://github.com/mingzhanliao "mingzhanliao (1 commits)")

### Embed Badge

![Health badge](/badges/mcjy-rule-engine/health.svg)

```
[![Health](https://phpackages.com/badges/mcjy-rule-engine/health.svg)](https://phpackages.com/packages/mcjy-rule-engine)
```

###  Alternatives

[wapmorgan/php-code-analyzer

A program that finds usage of different non-built-in extensions in your php code.

96149.1k4](/packages/wapmorgan-php-code-analyzer)[zepgram/magento-dotenv

Simple autoloader to integrate the Symfony Dotenv component into Magento2

1376.0k](/packages/zepgram-magento-dotenv)[fsc/batch

Library with classes to help you do batch.

185.3k](/packages/fsc-batch)

PHPackages © 2026

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