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

Created Updated Deleted Bundle Laravel Package

bespoke-support/created-updated-deleted-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel (Symfony-Compatible)

Since this is a Symfony bundle, Laravel integration requires Bridge or manual adaptation. For Laravel 5.5+ (Symfony 3.4+ compatible):

  1. Install via Composer (adjust for Laravel):

    composer require bespoke-support/created-updated-deleted-bundle
    
  2. Register the Bundle (Laravel 5.5+): In config/app.php, add to providers:

    BespokeSupport\CreatedUpdatedDeletedBundle\CreatedUpdatedDeletedBundle::class,
    
  3. Configure Database Events (Laravel-specific): Override boot() in a ServiceProvider to hook into Eloquent events:

    use BespokeSupport\CreatedUpdatedDeletedBundle\EventListener\TimestampListener;
    
    public function boot()
    {
        $this->app->make(TimestampListener::class)->subscribe();
    }
    
  4. Apply to a Model: Extend your Eloquent model:

    use BespokeSupport\CreatedUpdatedDeletedBundle\Traits\Timestampable;
    
    class Post extends Model
    {
        use Timestampable;
    }
    
  5. Run Migrations: Add columns to your table:

    Schema::table('posts', function (Blueprint $table) {
        $table->timestampsTz(); // For created_at/updated_at
        $table->timestamp('deleted_at')->nullable();
    });
    

First Use Case: Soft Deletes

Enable soft deletes in Post model:

use Illuminate\Database\Eloquent\SoftDeletes;

class Post extends Model
{
    use Timestampable, SoftDeletes;

    protected $dates = ['deleted_at'];
}

Now Post::where('deleted_at', null) filters active records.


Implementation Patterns

1. Automatic Timestamp Handling

  • Created/Updated: Automatically managed by Laravel’s timestamps() and updated_at logic.
  • Deleted: Use deleted_at for soft deletes (compatible with Laravel’s SoftDeletes trait).
  • Custom Fields: Override getCreatedAtColumn(), getUpdatedAtColumn(), or getDeletedAtColumn() in your model.

2. Event-Driven Workflows

Leverage Laravel events to extend functionality:

// In a ServiceProvider
Event::listen('eloquent.saving: Post', function ($model) {
    // Custom logic before save
});

Event::listen('eloquent.deleting: Post', function ($model) {
    $model->deleted_at = now(); // Force soft delete
});

3. Integration with API Resources

Return timestamps in API responses:

// PostResource.php
public function toArray($request)
{
    return [
        'id' => $this->id,
        'created_at' => $this->created_at->toDateTimeString(),
        'updated_at' => $this->updated_at->toDateTimeString(),
        'deleted_at' => $this->deleted_at ? $this->deleted_at->toDateTimeString() : null,
    ];
}

4. Query Scopes

Add reusable scopes:

class Post extends Model
{
    public function scopeActive($query)
    {
        return $query->whereNull('deleted_at');
    }

    public function scopeCreatedSince($query, $since)
    {
        return $query->where('created_at', '>=', $since);
    }
}

Usage:

Post::active()->createdSince(now()->subDays(7))->get();

5. Bulk Operations

Handle bulk updates/deletes with timestamps:

// Soft delete multiple records
Post::where('user_id', 1)->update(['deleted_at' => now()]);

// Restore deleted records
Post::whereNotNull('deleted_at')->update(['deleted_at' => null]);

Gotchas and Tips

1. Laravel-Symfony Compatibility Quirks

  • Doctrine vs. Eloquent: The bundle assumes Doctrine ORM. For Laravel, manually bind the TimestampListener to Eloquent events (as shown in Getting Started).
  • Timezone Handling: Use timestampsTz() in migrations for timezone-aware timestamps (Laravel 5.6+).

2. Debugging

  • Missing Timestamps: Ensure:
    • The trait is used in the model.
    • The columns exist in the database.
    • No touch() or save() overrides block automatic updates.
  • Soft Deletes: Verify $dates property includes deleted_at:
    protected $dates = ['deleted_at'];
    

3. Performance Tips

  • Indexing: Add database indexes for created_at, updated_at, and deleted_at:
    Schema::table('posts', function (Blueprint $table) {
        $table->index('created_at');
        $table->index('updated_at');
        $table->index('deleted_at');
    });
    
  • Avoid N+1: Use with() for eager loading:
    Post::with('author')->active()->get();
    

4. Extension Points

  • Custom Logic: Override setCreatedAt(), setUpdatedAt(), or setDeletedAt() in your model.
  • Audit Trails: Combine with laravel-auditlog to log changes to these fields:
    use Owlish\AuditLog\AuditLoggable;
    
    class Post extends Model
    {
        use Timestampable, AuditLoggable;
    }
    

5. Migration Pitfalls

  • Existing Tables: If adding to an existing table, run:
    php artisan migrate --path=/path/to/migrations
    
  • Data Integrity: For deleted_at, ensure nullable() is set to avoid constraint errors.

6. Testing

  • Factories: Seed timestamps in factories:
    $factory->define(Post::class, function (Faker $faker) {
        return [
            'created_at' => $faker->dateTimeThisYear,
            'updated_at' => $faker->dateTimeThisMonth,
            'deleted_at' => null,
        ];
    });
    
  • Soft Delete Tests:
    $post = Post::create([...]);
    $post->delete(); // Soft delete
    $this->assertSoftDeleted($post);
    $this->assertNull(Post::where('id', $post->id)->first());
    
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui