Install the Bundle
composer require chanondb/sequence-bundle
Register the bundle in config/bundles.php:
return [
// ...
Chanondb\SequenceBundle\ChanondbSequenceBundle::class => ['all' => true],
];
Create a Sequence Entity
Extend BaseSequence and define an id field:
// src/Entity/Sequence.php
namespace App\Entity;
use Chanondb\SequenceBundle\Model\Sequence as BaseSequence;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: "App\Repository\SequenceRepository")]
class Sequence extends BaseSequence
{
#[ORM\Id, ORM\GeneratedValue, ORM\Column]
private ?int $id = null;
}
Configure the Bundle
Define the sequence class in config/packages/chanondb_sequence.yaml:
chanondb_sequence:
orm:
class: App\Entity\Sequence
manager_name: default
Run Migrations
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
Generate a Sequence
Use the SequenceManager in a service or controller:
use Chanondb\SequenceBundle\Manager\SequenceManager;
public function __construct(private SequenceManager $sequenceManager) {}
public function generateOrderNumber(): string
{
return $this->sequenceManager->getNextSequence('order');
}
Generating Sequences
SequenceManager to fetch the next value for a given key:
$nextId = $sequenceManager->getNextSequence('user_id');
USER-{YYYYMMDD}-{SEQUENCE}):
chanondb_sequence:
formats:
user_id: "USER-{Y}-{M}-{D}-{S}"
Resetting Counters
$sequenceManager->resetSequence('order', 1000);
Batch Generation
$sequenceManager->getNextSequence('invoice', 5); // Returns array of 5 IDs
postPersist/postUpdate to auto-generate IDs:
$entity->setId($sequenceManager->getNextSequence('entity_key'));
$builder->add('id', HiddenType::class, [
'data' => $sequenceManager->getNextSequence('form_key'),
]);
ORD-2023-001):
return response()->json(['order_id' => $sequenceManager->getNextSequence('order')]);
SequenceManager or override getNextSequence():
class CustomSequenceManager extends SequenceManager
{
protected function getNextSequence(string $key, int $step = 1): int
{
// Custom logic (e.g., check cache first)
return parent::getNextSequence($key, $step);
}
}
chanondb_sequence:
managers:
primary:
class: App\Entity\Sequence
manager_name: default
secondary:
class: App\Entity\Sequence
manager_name: secondary
Race Conditions
SELECT ... FOR UPDATE to lock rows during generation. Ensure your database supports row-level locking (e.g., PostgreSQL, MySQL InnoDB).Schema Mismatches
Sequence entity schema changes, run migrations before generating sequences to avoid errors.doctrine:schema:validate to catch issues early:
php bin/console doctrine:schema:validate
Format Parsing Errors
{Y}-{M}-{D}) must match PHP’s DateTime placeholders. Invalid placeholders (e.g., {ZZZ}) will throw exceptions.DateTime object first:
$date = new DateTime();
$formatted = $date->format('Y-M-D'); // Validate before using in config.
Manager Name Mismatch
manager_name in config doesn’t match Doctrine’s connection name, sequences will fail silently or throw EntityManager errors.$this->sequenceManager->getEntityManager()->getConnection()->getDatabase();
doctrine:
dbal:
logging: true
profiling: true
Sequence entity is properly mapped:
php bin/console debug:container Chanondb\SequenceBundle\Model\Sequence
resetSequence() method sparingly in production. For testing, consider a separate test database.Custom Storage
SequenceRepository to use a non-Doctrine storage (e.g., Redis):
class RedisSequenceRepository implements SequenceRepositoryInterface
{
public function getNextSequence(string $key, int $step = 1): int
{
// Custom Redis logic
}
}
Event Listeners
$eventDispatcher->addListener(
SequenceEvents::POST_GENERATE,
function (SequenceEvent $event) {
// $event->getSequenceKey(), $event->getNextValue()
}
);
Batch Optimization
$sequenceManager->getNextSequence('batch_key', 100); // Generate 100 at once
manager_name is omitted, the bundle defaults to 'default'. Ensure your Doctrine connection is named accordingly.'order') are case-sensitive. Use consistent casing across your application.$step parameter in getNextSequence() defaults to 1. Using values > 1 can cause gaps in sequences if not managed carefully.How can I help you explore Laravel packages today?