hejunjie/trade-splitter

一个灵活、可扩展的交易/利润分账组件,提供百分比、固定金额、阶梯与递归分账等内置策略,并支持注册自定义策略 | A flexible and scalable transaction/profit sharing component, offering built-in strategies such as percentage, fixed amount, tiered, and recursive sharing, and supporting the registration of custom strategies

Installs: 0

Dependents: 0

Suggesters: 0

Security: 0

Stars: 7

Watchers: 0

Forks: 2

Open Issues: 0

pkg:composer/hejunjie/trade-splitter

v1.0.0 2025-10-13 10:13 UTC

This package is auto-updated.

Last update: 2025-11-29 04:44:37 UTC


README

PHP Trade Splitter

English简体中文

A flexible and extensible trade/profit distribution component.
Built-in strategies include Percentage, Fixed Amount, Ladder, and Recursive, and you can easily register custom strategies.

Perfect for multi-level commissions, e-commerce settlements, platform fees, and agent profit sharing.

This project has been parsed by Zread. If you need a quick overview of the project, you can click here to view it:Understand this project

✨ Features

  • 🔧 Multiple Strategies – 4 common built-in distribution modes
  • 🧩 Extensible Design – easily register your own strategy
  • Simple to Use – one static method does it all
  • 🧠 Clean Architecture – object-oriented with the Strategy pattern

📦 Installation

composer require hejunjie/trade-splitter

🚀 Quick Start

<?php

require __DIR__ . '/vendor/autoload.php';

use Hejunjie\TradeSplitter\Splitter;

// Percentage-based split (the sum of all rates must equal 1.0)
$allocations = Splitter::split(1000, [
    ['name' => 'Platform', 'rate' => 0.1],
    ['name' => 'Author', 'rate' => 0.9],
], 'percentage');

// Convert to array and print results
$result = array_map(fn($a) => $a->toArray(), $allocations);
print_r($result);

Example output:

Array
(
    [0] => Array
        (
            [name] => Platform
            [amount] => 100
            [ratio] => 0.1
        )

    [1] => Array
        (
            [name] => Author
            [amount] => 900
            [ratio] => 0.9
        )
)

🧩 Core Concepts

Concept Description
Splitter The main entry point — selects the strategy and performs the split
StrategyInterface Contract every strategy must implement:split(SplitContext $context): array
SplitContext Contains the split context (totalandparticipants)
Allocation Represents a split result withname,amount, andratio; providestoArray()

🧮 Built-in Strategies

Percentage Split percentage

Distributes amounts by percentage. The sum of all rate values must equal 1.0.

$result = Splitter::split(1000, [
    ['name' => 'Platform', 'rate' => 0.1],
    ['name' => 'Author', 'rate' => 0.9],
], 'percentage');

echo json_encode(array_map(fn($r) => $r->toArray(), $result), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . PHP_EOL;

// Output:
// [
//     {
//         "name": "Platform",
//         "amount": 100,
//         "ratio": 0.1
//     },
//     {
//         "name": "Author",
//         "amount": 900,
//         "ratio": 0.9
//     }
// ]

Fixed Amount Split fixed

Splits by fixed amounts. The total of all fixed values must not exceed the total amount.

$result = Splitter::split(3000, [
    ['name' => 'Agent A', 'amount' => 200],
    ['name' => 'Agent B', 'amount' => 300],
], 'fixed');

echo json_encode(array_map(fn($r) => $r->toArray(), $result), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . PHP_EOL;

// Output:
// [
//     {
//         "name": "Agent A",
//         "amount": 200,
//         "ratio": 0.0667
//     },
//     {
//         "name": "Agent B",
//         "amount": 300,
//         "ratio": 0.1
//     }
// ]

Ladder Split ladder

Applies different percentage rates based on amount tiers.
Use null for no upper limit.

$result = Splitter::split(5000, [
    [
        'name' => 'Agent A',
        'ladders' => [
            ['max' => 1000, 'rate' => 0.05],
            ['max' => 5000, 'rate' => 0.10],
            ['max' => null, 'rate' => 0.15],
        ],
    ],
    [
        'name' => 'Platform',
        'rate' => 0.05,
    ],
], 'ladder');

echo json_encode(array_map(fn($r) => $r->toArray(), $result), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . PHP_EOL;

// Output:
// [
//     {
//         "name": "Agent A",
//         "amount": 500,
//         "ratio": 0.1
//     },
//     {
//         "name": "Platform",
//         "amount": 250,
//         "ratio": 0.05
//     }
// ]

Recursive Split recursive

Each level’s share is calculated based on the remaining amount from the previous level.
Useful for multi-tier agent or channel commission systems.

$result = Splitter::split(10000, [
    ['name' => 'Level 1', 'rate' => 0.2],
    ['name' => 'Level 2', 'rate' => 0.2],
    ['name' => 'Level 3', 'rate' => 0.2],
], 'recursive');

echo json_encode(array_map(fn($r) => $r->toArray(), $result), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . PHP_EOL;

// Output:
// [
//     {
//         "name": "Level 1",
//         "amount": 1600,
//         "ratio": 0.2
//     },
//     {
//         "name": "Level 2",
//         "amount": 320,
//         "ratio": 0.2
//     },
//     {
//         "name": "Level 3",
//         "amount": 80,
//         "ratio": 0.2
//     }
// ]

🧠 Custom Strategy

Implement the Hejunjie\TradeSplitter\Contracts\StrategyInterface and register it:

use Hejunjie\TradeSplitter\Contracts\StrategyInterface;
use Hejunjie\TradeSplitter\Models\SplitContext;
use Hejunjie\TradeSplitter\Models\Allocation;
use Hejunjie\TradeSplitter\Splitter;

class MyStrategy implements StrategyInterface
{
    public function split(SplitContext $context): array
    {
        // Custom split logic
        // total: $context->total
        // participants: $context->participants
        return [
            new Allocation('someone', $context->total, 1.0)
        ];
    }
}

Splitter::registerStrategy('my_strategy', MyStrategy::class);

// Usage
$total = 1000;
$participants = [];
$result = Splitter::split($total, $participants, 'my_strategy');

🧪 Run the Demo

A demo script is included in the repository:

php tests/demo.php

This script demonstrates all four built-in strategies.

💡 Motivation

This component was born from my frustration with rigid, hard-coded profit-sharing logic in various projects.
I wanted a clear, pluggable, and reusable solution that could be integrated into any project — without reinventing the wheel each time.

If you’ve encountered strange or complex split scenarios in your business,
feel free to collaborate and help make this tool even more powerful!

🤝 Contributing

Got ideas, feedback, or found a bug? PRs and Issues are always welcome 🙌
If you find this project helpful, please consider giving it a ⭐ Star — that’s the biggest motivation for me to keep improving it!