baraja-core/variable-generator
Composer 安装命令:
composer require baraja-core/variable-generator
包简介
Generate new variable symbol by last variable and selected strategy.
README 文档
README
A smart PHP library for generating unique variable symbols, order numbers, and sequential identifiers in e-commerce applications. It handles complex problems like format specifications, transaction safety, duplicate prevention, and overflow management through pluggable strategies.
💡 Key Principles
- Automatic duplicate protection - Uses locking mechanism to prevent concurrent generation of the same number
- Pluggable strategies - Choose from built-in strategies or implement your own formatting logic
- Doctrine integration - Automatic entity discovery for seamless database integration
- Transaction safety - Built-in lock management ensures data integrity in high-concurrency environments
- Year-aware numbering - Default strategy automatically resets sequences on year change
- Zero configuration - Works out of the box with sensible defaults
🏗️ Architecture Overview
The library is built around a modular architecture with clear separation of concerns:
┌─────────────────────────────────────────────────────────────────┐
│ VariableGenerator │
│ (Main Entry Point) │
├─────────────────────────────────────────────────────────────────┤
│ │ │
│ ┌────────────────────┼────────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │VariableLoader│ │FormatStrategy│ │ Lock │ │
│ │ (Interface) │ │ (Interface) │ │ (External) │ │
│ └──────┬───────┘ └──────┬───────┘ └──────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────┐ ┌─────────────────────────────────┐ │
│ │DefaultOrder │ │ ┌─────────────────────────────┐ │ │
│ │VariableLoader│ │ │YearPrefixIncrementStrategy │ │ │
│ │ (Doctrine) │ │ ├─────────────────────────────┤ │ │
│ └──────────────┘ │ │SimpleIncrementStrategy │ │ │
│ │ ├─────────────────────────────┤ │ │
│ │ │Custom Strategy (Your Own) │ │ │
│ │ └─────────────────────────────┘ │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
🧩 Main Components
| Component | Description |
|---|---|
VariableGenerator |
Main service class that orchestrates number generation with locking and strategy execution |
VariableLoader |
Interface for retrieving the last used number from your data source |
FormatStrategy |
Interface defining how the next number should be calculated |
OrderEntity |
Interface for Doctrine entities that enables automatic loader discovery |
VariableGeneratorExtension |
Nette DI extension for framework integration |
VariableGeneratorAccessor |
Accessor interface for lazy service injection |
⚙️ Built-in Strategies
YearPrefixIncrementStrategy (Default)
Generates numbers in format YYXXXXXX where YY is the current year and XXXXXX is an incrementing sequence:
Year: 2024
Format: 24000001, 24000002, 24000003, ...
Year: 2025 (automatic reset on year change)
Format: 25000001, 25000002, 25000003, ...
Features:
- Automatic year prefix based on current date
- Automatic sequence reset on year change
- Configurable total length (default: 8 characters)
- Overflow protection (expands length if needed)
SimpleIncrementStrategy
A straightforward incrementing strategy that adds one to the previous number:
Input: 21000034
Output: 21000035
Features:
- Maintains consistent number length with zero-padding
- Configurable length (minimum: 4 characters)
- Falls back to year-prefixed first number if no previous exists
🚀 Basic Usage
Creating the Generator
use Baraja\VariableGenerator\VariableGenerator; use Baraja\VariableGenerator\Strategy\YearPrefixIncrementStrategy; // With Doctrine EntityManager (automatic entity discovery) $generator = new VariableGenerator( variableLoader: null, // Auto-discovered from Doctrine strategy: null, // Uses YearPrefixIncrementStrategy by default em: $entityManager, ); // With custom variable loader $generator = new VariableGenerator( variableLoader: new MyCustomVariableLoader(), strategy: new YearPrefixIncrementStrategy(length: 6), );
Generating Numbers
// Generate next number (automatically retrieves last used number) $newOrderNumber = $generator->generate(); // Result: 24000001 (if first order in 2024) // Generate next number based on specific previous value $newNumber = $generator->generate('24000034'); // Result: 24000035 // Get current (last used) number without generating new one $current = $generator->getCurrent(); // Result: 24000034
Using Custom Strategies
use Baraja\VariableGenerator\Strategy\SimpleIncrementStrategy; // Switch to simple increment strategy $generator->setStrategy(new SimpleIncrementStrategy(length: 10)); // Or use custom strategy at initialization $generator = new VariableGenerator( variableLoader: $loader, strategy: new SimpleIncrementStrategy(length: 8), );
🔐 Duplicate Prevention
This library automatically protects against generating duplicate numbers in high-concurrency environments. The protection mechanism works as follows:
- Wait for existing transactions - Before generating, the system waits if another process is currently generating
- Lock acquisition - A 15-second transaction lock is acquired for the generation process
- Number generation - The new number is calculated using the selected strategy
- Short protection window - A 1-second lock remains to allow saving the new entity to database
// The generate() method handles all locking automatically $number = $generator->generate(); // IMPORTANT: Save your entity immediately after generation! // Custom transaction name for different entity types $orderNumber = $generator->generate(transactionName: 'order-generator'); $invoiceNumber = $generator->generate(transactionName: 'invoice-generator');
Warning: You must save the generated number to your database within 1 second. After that, the lock is released and another process may generate the same number.
🔧 Custom Implementations
Custom Variable Loader
Implement the VariableLoader interface to retrieve the last number from your data source:
use Baraja\VariableGenerator\VariableLoader; final class MyCustomVariableLoader implements VariableLoader { public function __construct( private PDO $pdo, ) { } public function getCurrent(): ?string { $stmt = $this->pdo->query( 'SELECT order_number FROM orders ORDER BY id DESC LIMIT 1' ); $result = $stmt->fetchColumn(); return $result !== false ? (string) $result : null; } }
Custom Format Strategy
Implement the FormatStrategy interface for custom number formatting:
use Baraja\VariableGenerator\Strategy\FormatStrategy; final class MonthlyResetStrategy implements FormatStrategy { public function generate(string $last): string { $prefix = date('ym'); // e.g., "2401" for January 2024 if (str_starts_with($last, $prefix)) { $sequence = (int) substr($last, 4); return $prefix . str_pad((string) ($sequence + 1), 4, '0', STR_PAD_LEFT); } return $this->getFirst(); } public function getFirst(): string { return date('ym') . '0001'; } }
Doctrine Entity Integration
Implement the OrderEntity interface on your Doctrine entity for automatic discovery:
use Baraja\VariableGenerator\Order\OrderEntity; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity] class Order implements OrderEntity { #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column(type: 'integer')] private ?int $id = null; #[ORM\Column(type: 'string', unique: true)] private string $number; #[ORM\Column(type: 'datetime')] private \DateTime $insertedDate; public function getId(): ?int { return $this->id; } public function getNumber(): string { return $this->number; } public function getInsertedDate(): \DateTime { return $this->insertedDate; } }
Note: If your entity has
getInsertedDate()method, theDefaultOrderVariableLoaderwill automatically filter orders from the last year when searching for the latest number.
⚡ Nette Framework Integration
Register the extension in your configuration:
extensions: variableGenerator: Baraja\VariableGenerator\VariableGeneratorExtension
Then inject the generator into your services:
final class OrderFacade { public function __construct( private VariableGenerator $generator, ) { } public function createOrder(array $data): Order { $order = new Order(); $order->setNumber((string) $this->generator->generate()); // ... save order return $order; } }
For lazy loading, use the accessor:
public function __construct( private VariableGeneratorAccessor $generatorAccessor, ) { } public function process(): void { $generator = $this->generatorAccessor->get(); // ... }
⚠️ Important Considerations
-
Save immediately - Always save the generated number to your database immediately after calling
generate(). The lock protection lasts only 1 second. -
Single entity per interface - If using automatic Doctrine discovery, only one entity can implement
OrderEntity. For multiple entities, implement customVariableLoaderservices. -
No caching - The
VariableLoader::getCurrent()method should always fetch real data from the database. Never use cached values. -
Transaction safety - The generator uses the
baraja-core/locklibrary for thread safety. Make sure this dependency is properly installed.
📦 Installation
It's best to use Composer for installation, and you can also find the package on Packagist and GitHub.
To install, simply use the command:
$ composer require baraja-core/variable-generator
You can use the package manually by creating an instance of the internal classes, or register a DIC extension to link the services directly to the Nette Framework.
Requirements
- PHP 8.0 or higher
baraja-core/lockpackage (installed automatically)- Doctrine ORM (optional, for automatic entity discovery)
- Nette DI (optional, for framework integration)
👤 Author
Jan Barášek - https://baraja.cz
📄 License
baraja-core/variable-generator is licensed under the MIT license. See the LICENSE file for more details.
baraja-core/variable-generator 适用场景与选型建议
baraja-core/variable-generator 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 3.7k 次下载、GitHub Stars 达 1, 最近一次更新时间为 2021 年 01 月 12 日, 在 PHP 生态内属于活跃度较高的组件。
我们在过去多个企业项目中使用过 baraja-core/variable-generator 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 baraja-core/variable-generator 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
统计信息
- 总下载量: 3.7k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 1
- 依赖项目数: 1
- 推荐数: 0
其他信息
- 授权协议: Unknown
- 更新时间: 2021-01-12