Weave Code
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

Timestampable Bundle Laravel Package

andanteproject/timestampable-bundle

Symfony bundle for Doctrine entities that automatically manages createdAt and updatedAt with DateTimeImmutable. Zero config to start, customizable, uses Symfony Clock, no attributes needed, and won’t overwrite timestamps you set manually. Compatible with Symfony 5–8, PHP 8.2.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require andanteproject/timestampable-bundle
    

    Register the bundle in config/bundles.php (Symfony Flex handles this automatically).

  2. Enable for an Entity: Add TimestampableInterface and TimestampableTrait to your entity:

    use Andante\TimestampableBundle\Timestampable\{TimestampableInterface, TimestampableTrait};
    
    #[ORM\Entity]
    class Article implements TimestampableInterface
    {
        use TimestampableTrait;
    
        // ... existing fields
    }
    
  3. Update Schema: Run migrations or schema updates to add created_at and updated_at columns.

First Use Case

Audit Logging: Track when records are created/updated without manual timestamp management. Example:

$article = new Article('New Post');
$entityManager->persist($article); // Automatically sets `createdAt` and `updatedAt`

Implementation Patterns

Core Workflows

  1. Default Usage (Traits + Interfaces):

    • Use TimestampableTrait for both createdAt and updatedAt.
    • No annotations or attributes needed; Doctrine handles column mapping via naming strategy.
  2. Selective Timestamping:

    • Track only createdAt:
      use Andante\TimestampableBundle\Timestampable\{CreatedAtTimestampableInterface, CreatedAtTimestampableTrait};
      
      class Article implements CreatedAtTimestampableInterface
      {
          use CreatedAtTimestampableTrait;
      }
      
    • Track only updatedAt:
      use Andante\TimestampableBundle\Timestampable\{UpdatedAtTimestampableInterface, UpdatedAtTimestampableTrait};
      
      class Article implements UpdatedAtTimestampableInterface
      {
          use UpdatedAtTimestampableTrait;
      }
      
  3. Custom Property/Column Names: Override defaults in config/packages/andante_timestampable.yaml:

    andante_timestampable:
      default:
        created_at_property_name: createdOn
        updated_at_column_name: last_modified
    

Integration Tips

  • Symfony Events: Listen to prePersist/preUpdate to log actions before timestamps update.
  • API Platform: Use createdAt/updatedAt in serializers for consistent JSON responses.
  • Migrations: Prefer Doctrine Migrations over schema updates for production:
    php bin/console make:migration
    php bin/console doctrine:migrations:migrate
    

Gotchas and Tips

Pitfalls

  1. Metadata Cache Stale:

    • After updating entity classes, clear the cache:
      php bin/console cache:clear
      
    • Enable metadata_cache_warmer_enabled: true in production to avoid first-request delays.
  2. Explicit Overrides:

    • The bundle respects manually set createdAt/updatedAt values. To force updates:
      $article->setUpdatedAt(null); // Triggers auto-update
      
  3. Naming Conflicts:

    • If your entity already has createdAt/updatedAt properties, exclude them from Doctrine mapping:
      #[ORM\Column(ignore: true)]
      private ?\DateTimeImmutable $createdAt;
      

Debugging

  • Check Metadata: Inspect cached metadata at %kernel.cache_dir%/timestampable_metadata.php.
  • Symfony Clock: Use symfony/clock for testing time-sensitive logic:
    $this->clock = new FrozenClock(new \DateTimeImmutable('2023-01-01'));
    

Extension Points

  1. Custom Time Sources: Inject a custom ClockInterface via dependency injection:

    services:
        App\Service\CustomClock:
            arguments:
                $clock: '@andante_timestampable.clock'
    
  2. Event Subscribers: Extend timestamp logic via TimestampableEvents:

    use Andante\TimestampableBundle\Event\TimestampableEvents;
    
    $dispatcher->addListener(TimestampableEvents::PRE_UPDATE, function ($event) {
        if ($event->getEntity() instanceof Article) {
            // Custom logic
        }
    });
    
  3. Legacy Systems: Use the "no-trait" approach for entities with non-standard property names:

    class LegacyArticle implements TimestampableInterface
    {
        private ?\DateTimeImmutable $created = null;
        private ?\DateTimeImmutable $modified = null;
    
        // Implement getters/setters for `created`/`modified`
    }
    

    Configure in andante_timestampable.yaml:

    andante_timestampable:
      entity:
        App\Entity\LegacyArticle:
            created_at_property_name: created
            updated_at_property_name: modified
    
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.
aimeos/prisma
besmartand-pro/php-quality-config
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor
spatie/laravel-javascript-views