Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Sequence Bundle Laravel Package

chanondb/sequence-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to First Use

  1. Install the Bundle

    composer require chanondb/sequence-bundle
    

    Register the bundle in config/bundles.php:

    return [
        // ...
        Chanondb\SequenceBundle\ChanondbSequenceBundle::class => ['all' => true],
    ];
    
  2. 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;
    }
    
  3. Configure the Bundle Define the sequence class in config/packages/chanondb_sequence.yaml:

    chanondb_sequence:
        orm:
            class: App\Entity\Sequence
            manager_name: default
    
  4. Run Migrations

    php bin/console doctrine:migrations:diff
    php bin/console doctrine:migrations:migrate
    
  5. 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');
    }
    

Implementation Patterns

Core Workflows

  1. Generating Sequences

    • Use SequenceManager to fetch the next value for a given key:
      $nextId = $sequenceManager->getNextSequence('user_id');
      
    • Supports custom formats (e.g., USER-{YYYYMMDD}-{SEQUENCE}):
      chanondb_sequence:
          formats:
              user_id: "USER-{Y}-{M}-{D}-{S}"
      
  2. Resetting Counters

    • Reset a sequence to a specific value (e.g., for testing):
      $sequenceManager->resetSequence('order', 1000);
      
  3. Batch Generation

    • Generate multiple sequences in a transaction:
      $sequenceManager->getNextSequence('invoice', 5); // Returns array of 5 IDs
      

Integration Tips

  • Doctrine Events: Hook into postPersist/postUpdate to auto-generate IDs:
    $entity->setId($sequenceManager->getNextSequence('entity_key'));
    
  • Symfony Forms: Use for auto-incrementing fields:
    $builder->add('id', HiddenType::class, [
        'data' => $sequenceManager->getNextSequence('form_key'),
    ]);
    
  • API Responses: Return formatted sequences (e.g., ORD-2023-001):
    return response()->json(['order_id' => $sequenceManager->getNextSequence('order')]);
    

Advanced Patterns

  • Custom Sequence Logic: Extend 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);
        }
    }
    
  • Multi-Database Support: Configure separate managers for each database:
    chanondb_sequence:
        managers:
            primary:
                class: App\Entity\Sequence
                manager_name: default
            secondary:
                class: App\Entity\Sequence
                manager_name: secondary
    

Gotchas and Tips

Common Pitfalls

  1. Race Conditions

    • The bundle uses SELECT ... FOR UPDATE to lock rows during generation. Ensure your database supports row-level locking (e.g., PostgreSQL, MySQL InnoDB).
    • Fix: If using SQLite, consider adding a retry mechanism or use a distributed lock (e.g., Redis).
  2. Schema Mismatches

    • If the Sequence entity schema changes, run migrations before generating sequences to avoid errors.
    • Tip: Use doctrine:schema:validate to catch issues early:
      php bin/console doctrine:schema:validate
      
  3. Format Parsing Errors

    • Custom formats (e.g., {Y}-{M}-{D}) must match PHP’s DateTime placeholders. Invalid placeholders (e.g., {ZZZ}) will throw exceptions.
    • Debug: Test formats in a DateTime object first:
      $date = new DateTime();
      $formatted = $date->format('Y-M-D'); // Validate before using in config.
      
  4. Manager Name Mismatch

    • If manager_name in config doesn’t match Doctrine’s connection name, sequences will fail silently or throw EntityManager errors.
    • Tip: Verify with:
      $this->sequenceManager->getEntityManager()->getConnection()->getDatabase();
      

Debugging Tips

  • Log Sequence Queries: Enable Doctrine logging to inspect SQL:
    doctrine:
        dbal:
            logging: true
            profiling: true
    
  • Check Entity Existence: Ensure the Sequence entity is properly mapped:
    php bin/console debug:container Chanondb\SequenceBundle\Model\Sequence
    
  • Reset Sequences Safely: Use the resetSequence() method sparingly in production. For testing, consider a separate test database.

Extension Points

  1. Custom Storage

    • Override 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
          }
      }
      
    • Update the bundle config to point to your repository.
  2. Event Listeners

    • Listen for sequence generation events (e.g., log sequences or trigger side effects):
      $eventDispatcher->addListener(
          SequenceEvents::POST_GENERATE,
          function (SequenceEvent $event) {
              // $event->getSequenceKey(), $event->getNextValue()
          }
      );
      
  3. Batch Optimization

    • For high-throughput systems, batch sequence generation to reduce database round-trips:
      $sequenceManager->getNextSequence('batch_key', 100); // Generate 100 at once
      

Configuration Quirks

  • Default Manager Name: If manager_name is omitted, the bundle defaults to 'default'. Ensure your Doctrine connection is named accordingly.
  • Case Sensitivity: Sequence keys (e.g., 'order') are case-sensitive. Use consistent casing across your application.
  • Step Parameter: The $step parameter in getNextSequence() defaults to 1. Using values > 1 can cause gaps in sequences if not managed carefully.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
djstarcom/laravel-breadcrumbs
djstarcom/laravel-server-timing
class-atlas/laravel-flitt
ipregistry/ipregistry-laravel
daimakuai-ext/config
tomassalazarlopez/laravel-filemanager
ergare17/tasks
magentron/elasticemail-php
anilcancakir/laravel-agent-mcp
callcocam/laravel-whatsapp-cloud
winavin/permissions
daimakuai-ext/reporter
springjk/laravel-admin
kwaadpepper/laravel-storage-manager
karlerss/laravel-db-script-manager
hexincorp/laravel-debugbar
quellabs/canvas
quellabs/annotation-reader
mydnic/volet-feature-board
wmde/fundraising-phpcs