eg-mohamed/referenceable
Laravel package that adds reference numbers to Eloquent models with configurable formats. Supports random, sequential, and template-based generation (e.g., year/month/seq/random), collision handling, validation, and tenant-aware sequences. Includes install command, config publishing, and Laravel 10–...
Installation:
composer require eg-mohamed/referenceable
php artisan referenceable:install
Add Column to Migration:
Schema::create('orders', function (Blueprint $table) {
$table->string('reference')->unique()->index();
// ...
});
Apply Trait to Model:
use MohamedSaid\Referenceable\Traits\HasReference;
class Order extends Model {
use HasReference;
}
First Use Case:
$order = Order::create(['customer_id' => 1]);
echo $order->reference; // Auto-generated (e.g., "ORD-123456")
config/referenceable.php for global defaults.HasReference for model-specific overrides.php artisan referenceable --list for CLI tools.Automatic Generation:
// Model saves with reference automatically
$invoice = Invoice::create(['amount' => 100]);
Manual Generation:
$ticket = new SupportTicket();
$ticket->generateReference(); // Force generation
$ticket->save();
Batch Processing:
// CLI: Generate references for 1,000 existing records
php artisan referenceable:generate App\Models\Order --batch=500
Validation:
// Form request validation
$request->validate([
'reference' => 'required|reference_format:ORD-\d{6}'
]);
Query Scopes:
// Find by reference
$order = Order::findByReference('ORD-123456');
// Filter by prefix
$todayOrders = Order::referenceStartsWith('ORD-2024')->get();
Multi-Tenancy:
class Order extends Model {
use HasReference;
protected $referenceUniquenessScope = 'tenant';
protected $referenceTenantColumn = 'company_id';
}
// Dynamic references with placeholders
protected $referenceTemplate = [
'format' => '{PREFIX}{YEAR}{SEQ}',
'sequence_length' => 4,
];
INV20240001).Collision Handling:
retry (auto-retry on collision).collision_strategy: fail to throw exceptions for debugging.max_retries (default: 100) to avoid infinite loops.Sequential Reset:
reset_frequency: yearly resets counters at year start.php artisan referenceable:stats to verify reset logic.Performance:
use_transactions for bulk operations if ACID isn’t critical.'cache_config': true for high-traffic models.php artisan referenceable:validate App\Models\Order --fix
php artisan referenceable:stats App\Models\Order --json
Custom Strategies:
// Extend the generator
class CustomStrategy extends \MohamedSaid\Referenceable\Strategies\BaseStrategy {
public function generate() { ... }
}
Register in config/referenceable.php:
'strategies' => [
'custom' => \App\Strategies\CustomStrategy::class,
],
Placeholder Extensions:
Override getTemplatePlaceholders() in your model to add custom placeholders (e.g., {CUSTOM}).
Event Hooks:
Listen for referenceable.generated or referenceable.collision events:
Event::listen('referenceable.generated', function ($model, $reference) {
// Log or notify
});
Backward Compatibility:
Old properties (e.g., $referenceLength) still work but prefer the new array format:
// Old (still supported)
protected $referenceLength = 8;
// New (recommended)
protected $referenceTemplate = ['random_length' => 8];
Global vs. Model Overrides:
Model properties override global config. Use php artisan referenceable:stats to verify active settings.
Indexing:
Add indexes to reference columns and tenant columns (if multi-tenant):
Schema::table('orders', function (Blueprint $table) {
$table->index('reference');
$table->index(['company_id', 'reference']);
});
Batch Size:
Adjust 'batch_size': 1000 in config/referenceable.php for bulk operations.
Caching:
Enable 'cache_config': true to cache model configurations (reduces DB lookups).
How can I help you explore Laravel packages today?