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

Doctrine Orm Extensions Bundle Laravel Package

symfonylab/doctrine-orm-extensions-bundle

A Symfony bundle that extends Doctrine ORM with reusable entity behaviors and utilities, helping you cut boilerplate and keep persistence logic clean. Install it via Composer, enable the bundle, and configure the extensions your project needs.

View on GitHub
Deep Wiki
Context7

Getting Started

Start by confirming the package version and reviewing the trait source before wiring it into models:

composer require <vendor>/<package>:^1.1

Look first at:

  1. The MutableMicrosecondsTrait implementation — specifically which attributes it touches and whether it overrides existing casts, accessors, or mutators.
  2. The model event or boot logic that sets created_at when it is not already set.
  3. Any migration/schema expectations — microsecond support requires datetime(6) / timestamp(6) (MySQL/PostgreSQL) rather than second-precision columns.

Minimal first use case: add the trait to a model that records time-sensitive events, then create a record without passing created_at:

use Vendor\Package\Concerns\MutableMicrosecondsTrait;

class AuditEvent extends Model
{
    use MutableMicrosecondsTrait;

    protected $guarded = [];
}

$event = AuditEvent::create([
    'type' => 'login',
]);

// created_at should now be populated automatically,
// and should retain microsecond precision if the schema supports it.
dump($event->created_at->format('Y-m-d H:i:s.u'));

Verify the stored value after save, not just the in-memory model. Query the row back and inspect the raw database value:

dump($event->fresh()->getRawOriginal('created_at'));

If the value comes back with .000000, the trait is working but the column precision is not.

Implementation Patterns

Apply the trait at the right level

For packages with many time-sensitive models, put the trait on a shared base model. For isolated use cases, apply it only to models where sub-second ordering matters.

abstract class BaseModel extends Model
{
    use MutableMicrosecondsTrait;
}

Avoid applying it globally if only a few tables use microsecond columns; otherwise you create inconsistent behavior between models.

Combine with explicit casts

Use explicit datetime casts so Laravel and the trait agree on the expected type and format:

protected $casts = [
    'created_at' => 'datetime',
    'updated_at' => 'datetime',
    'occurred_at' => 'datetime',
];

If the trait changes how date attributes are mutated, keep custom datetime fields in the same cast style to avoid mixed mutable/immutable behavior.

Let the package fill created_at

The new behavior is most useful when creating records through Eloquent:

$event = AuditEvent::create([
    'type' => 'payment.captured',
    'payload' => $payload,
]);

Do not manually set created_at unless you need to backfill or import historical data. If you do set it, confirm the package respects your value rather than overwriting it:

AuditEvent::create([
    'type' => 'imported',
    'created_at' => now()->subDay(),
]);

Use it for ordering and audit trails

Microsecond precision is most valuable for append-only tables, event logs, and high-frequency audit records. Pair it with a deterministic secondary sort:

AuditEvent::query()
    ->orderByDesc('created_at')
    ->orderByDesc('id')
    ->get();

Do not assume microsecond timestamps are globally unique. Concurrent writes can still share the same microsecond value.

Factories and seeders

In factories, prefer relative timestamps and only override created_at when the test depends on it:

public function definition(): array
{
    return [
        'type' => 'test',
        // created_at is intentionally omitted so the package fills it.
    ];
}

For time-sensitive tests, combine the package with Laravel time travel:

$this->travelTo(now()->setMicrosecond(123456));

$event = AuditEvent::create(['type' => 'test']);

$this->assertSame(123456, $event->created_at->microsecond);

API resources and serialization

If clients depend on microsecond precision, format explicitly in resources:

return [
    'created_at' => $this->created_at?->format('Y-m-d\TH:i:s.uP'),
];

Do not assume Laravel’s default JSON date serialization preserves microseconds. It often does not.

Gotchas and Tips

Database precision is the most common failure point

The trait can only preserve microseconds if the underlying column stores them. Check migrations:

$table->timestamp('created_at', 6)->nullable();

For MySQL, timestamp without precision truncates to seconds. For PostgreSQL, use timestamp(6). SQLite stores dates as text and behaves differently, so test against the database engine you deploy on.

Auto-filling created_at is a behavioral change

This release changes model state before save. Code that previously checked is_null($model->created_at) before persistence may now see a value earlier than expected:

$event = new AuditEvent(['type' => 'test']);

// Depending on when the package sets created_at,
// this may no longer be null before save.
dump($event->created_at);

Audit any model observers, policies, or validation rules that assume created_at is null until after save().

Mutable datetime objects can leak state

A “mutable” trait means date objects may be modified in place. Avoid sharing the same Carbon instance across models or attributes:

$now = now();

$eventA->created_at = $now;
$eventB->created_at = $now;

$eventA->created_at->addMinute();

// $eventB->created_at may also change if the same mutable instance is shared.

Clone when assigning shared values:

$eventB->created_at = $now->copy();

Trait conflicts with existing accessors and mutators

If your model already defines a created_at accessor, mutator, or custom cast, inspect how the trait composes with it. Trait methods can be overridden by the class, but event listeners and boot methods may still run. Use getAttribute, getRawOriginal, and getDirty to debug the final value.

Serialization may hide microseconds

Even if the database stores microseconds, toArray() or toJson() may use a lower-precision format. Override serializeDate() on the model if needed:

protected function serializeDate(DateTimeInterface $date): string
{
    return $date->format('Y-m-d\TH:i:s.uP');
}

Timezone handling is unchanged

Microseconds do not solve timezone issues. Continue storing timestamps in UTC and converting at the presentation boundary. Confirm whether the trait uses config('app.timezone') or the model’s $timezone property.

Testing checklist

When upgrading to 1.1.0, run tests that cover:

  • Creating a model without created_at.
  • Creating a model with an explicit created_at.
  • Reading the raw database value after save.
  • JSON serialization of datetime fields.
  • Ordering by created_at with multiple records created in the same request.
  • Models that already define datetime casts or accessors.

Extension points

Check whether the trait exposes overridable methods for timestamp generation or attribute selection. If it does, prefer overriding those methods in a base model over copying trait logic. If it does not, keep the trait application narrow and wrap custom behavior in model events rather than patching vendor code.

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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle