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

Laravel Blamable Laravel Package

astalpaert/laravel-blamable

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require astalpaert/laravel-blamable
    

    Run migrations (if using the default schema):

    php artisan migrate
    
  2. Model Integration: Use the Blamable trait in your Eloquent model:

    use Astalpaert\Blamable\Blamable;
    
    class Post extends Model
    {
        use Blamable;
    }
    
  3. First Use Case: Automatically track who created/updated a record:

    $post = new Post(['title' => 'Hello World']);
    $post->save(); // Automatically sets `created_by` and `updated_by` to the authenticated user
    

Key Files to Review

  • config/blamable.php (customization options)
  • database/migrations/ (default schema for created_by/updated_by columns)
  • src/Blamable.php (trait logic)

Implementation Patterns

Core Workflows

  1. Automatic Tracking:

    // No manual intervention needed; works with Laravel's default auth
    $user = auth()->user();
    $post = new Post(['title' => 'Test']);
    $post->save(); // `created_by` = `$user->id`, `updated_by` = `$user->id`
    
  2. Manual Overrides:

    // Force a specific user (e.g., for API calls or admin actions)
    $post = new Post(['title' => 'Admin Post']);
    $post->setCreatedBy($adminUser);
    $post->setUpdatedBy($adminUser);
    $post->save();
    
  3. Query Scopes:

    // Filter by creator
    $userPosts = Post::byUser($user)->get();
    
    // Filter by updater
    $recentlyUpdated = Post::updatedBy($user)->latest()->take(5)->get();
    

Integration Tips

  • APIs: Use middleware to set a default user (e.g., service accounts):
    // In middleware
    $request->user = $serviceAccountUser;
    
  • Seeding: Disable blamable for seeds if needed:
    Post::withoutBlamable(function () {
        Post::factory()->create();
    });
    
  • Soft Deletes: Works seamlessly with SoftDeletes trait.

Gotchas and Tips

Pitfalls

  1. Missing Columns:

    • If created_by/updated_by columns don’t exist, the trait silently fails. Always run migrations first or define the schema manually:
      Schema::table('posts', function (Blueprint $table) {
          $table->foreignId('created_by')->constrained()->nullOnDelete();
          $table->foreignId('updated_by')->constrained()->nullOnDelete();
      });
      
  2. Authentication Context:

    • Relies on Laravel’s auth system. If no user is authenticated, created_by/updated_by will be null. Handle this explicitly:
      $post->setCreatedBy(auth()->check() ? auth()->user() : null);
      
  3. Mass Assignment:

    • Avoid manually setting created_by/updated_by in mass assignment arrays. Use the trait methods instead.

Debugging

  • Log Missing Users: Add a listener to log when created_by/updated_by are null:

    Post::created(function ($post) {
        if (!$post->created_by) {
            Log::warning('Post created without a user', ['post_id' => $post->id]);
        }
    });
    
  • Check Trait Loading: Verify the trait is loaded in your model:

    dd(class_uses(Post::class)); // Should include `Blamable`
    

Extension Points

  1. Custom User Resolution: Override getBlamableUser() to fetch users from a non-standard source (e.g., API tokens):

    class Post extends Model
    {
        use Blamable;
    
        protected function getBlamableUser()
        {
            return $this->request?->user() ?? auth()->user();
        }
    }
    
  2. Additional Metadata: Extend the trait to track extra fields (e.g., created_ip):

    use Astalpaert\Blamable\Blamable as BaseBlamable;
    
    trait ExtendedBlamable {
        use BaseBlamable;
    
        protected static function booted()
        {
            static::creating(function ($model) {
                $model->created_ip = request()->ip();
            });
        }
    }
    
  3. Custom Query Scopes: Add reusable scopes to your model:

    class Post extends Model
    {
        use Blamable;
    
        public function scopeByTeam($query, Team $team)
        {
            return $query->whereHas('user', function ($q) use ($team) {
                $q->where('team_id', $team->id);
            });
        }
    }
    
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.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator