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

Laravel Userstamps Laravel Package

sansanlabs/laravel-userstamps

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:
    composer require sansanlabs/laravel-userstamps
    
  2. Publish the config (optional but recommended for customization):
    php artisan vendor:publish --tag="userstamps-config"
    
  3. Add migration macros to your model's migration file:
    Schema::create('posts', function (Blueprint $table) {
        $table->id();
        $table->string('title');
        $table->text('content');
        $table->userstamps(); // Adds created_by_id, updated_by_id
        $table->softUserstamps(); // Adds deleted_by_id (for soft deletes)
        $table->timestamps();
    });
    
  4. Apply the trait to your model:
    use SanSanLabs\UserStamps\Concerns\HasUserstamps;
    
    class Post extends Model
    {
        use HasUserstamps;
    }
    

First Use Case: Audit Trail

Automatically track who created/updated/deleted a record:

// In a controller or service
$post = new Post();
$post->title = 'Hello World';
$post->save();

// Access the creator
$user = $post->createdBy; // Returns the User model

Implementation Patterns

Core Workflow: Model Integration

  1. Migration Setup:

    • Use userstamps() for basic tracking (created_by, updated_by).
    • Use softUserstamps() if soft deletes are enabled (adds deleted_by).
    • For polymorphic relationships (e.g., non-User creators), set is_using_morph: true in config.
  2. Model-Level Access:

    // Accessors provided by the trait
    $post->createdBy;    // User who created the record
    $post->updatedBy;    // User who last updated
    $post->deletedBy;    // User who soft-deleted (if applicable)
    
  3. Automatic Population:

    • The package hooks into Eloquent events (creating, updating, deleting).
    • Default behavior: Uses the authenticated user from Laravel’s Auth::user().
    • Override: Manually set via $model->createdBy = $user;.

Advanced Patterns

1. Polymorphic Userstamps

Enable in config:

'is_using_morph' => true,
  • Adds _type columns (e.g., created_by_id, created_by_type).
  • Supports non-User models (e.g., Team, Organization) as creators.

2. Custom User Model

Override defaults in config:

'users_model' => App\Models\Admin::class,
'users_table' => 'admins',

3. Bulk Operations

For mass updates/creates, manually set the user:

Post::create([
    'title' => 'Bulk Post',
    'content' => '...',
], ['created_by_id' => $admin->id]); // Override default auth user

4. Query Scoping

Filter records by creator:

Post::whereCreatedBy($user)->get(); // Uses the trait's accessor
// Under the hood: where('created_by_id', $user->id)

5. Soft Deletes Integration

  • Enable with_trashed: true in config to include deleted records in queries.
  • Access deleted-by user:
    $post = Post::withTrashed()->find($id);
    $post->deletedBy; // Returns the User who deleted it
    

Integration Tips

  • Testing: Use actingAs() in Laravel’s testing helpers to simulate users:
    $this->actingAs($user)->post('/posts')->assertCreated();
    
  • APIs: Expose userstamps in responses for auditability:
    return PostResource::make($post)->additional(['created_by' => $post->createdBy]);
    
  • Events: Listen to created, updated, or deleted events to log actions:
    Post::created(function ($post) {
        Log::info("Post created by {$post->createdBy->name}");
    });
    

Gotchas and Tips

Pitfalls

  1. Migration Order:

    • Error: Column not found when running migrations.
    • Fix: Ensure userstamps() is called after the primary key ($table->id()) but before other columns.
    • Example:
      $table->id();
      $table->userstamps(); // Correct order
      $table->string('title');
      
  2. Polymorphic Conflicts:

    • Error: SQLSTATE[42S22]: Column not found when using morph with existing tables.
    • Fix: Disable morph (is_using_morph: false) or manually add _type columns before enabling morph.
  3. Soft Deletes + Userstamps:

    • Gotcha: deleted_by columns are ignored if soft deletes are disabled in the model.
    • Fix: Ensure both use SoftDeletes; and use HasUserstamps; are on the model.
  4. Auth User Unavailable:

    • Scenario: Userstamps fail silently if no user is authenticated.
    • Fix: Set a default user in config or handle null cases:
      $post->createdBy ??= User::find(1); // Fallback
      

Debugging Tips

  1. Check Config: Run php artisan config:clear if userstamps aren’t populating. Verify config values:

    php artisan config:get userstamps.*
    
  2. Event Hooks: Add debug logs to event listeners:

    Post::created(function ($post) {
        \Log::debug('Created by:', ['user_id' => $post->created_by_id]);
    });
    
  3. Database Schema: Verify columns exist:

    SHOW COLUMNS FROM posts LIKE '%by%';
    

    Expected output for non-morph:

    created_by_id | bigint
    updated_by_id | bigint
    deleted_by_id | bigint (if softUserstamps)
    

Extension Points

  1. Custom Accessors: Override the trait’s accessors in your model:

    public function getCreatedByAttribute($value) {
        return $value ? User::find($value)->name : 'System';
    }
    
  2. Dynamic User Resolution: Extend the package to resolve users dynamically (e.g., from API tokens):

    // In a service provider
    UserStamps::resolveUsing(function () {
        return Auth::guard('api')->user() ?? Auth::user();
    });
    
  3. Additional Stamps: Add custom stamps (e.g., published_by) by extending the trait:

    // In HasUserstamps.php (copy the trait and extend)
    public static function bootHasUserstamps() {
        static::created(function ($model) {
            $model->published_by_id = auth()->id();
        });
    }
    
  4. Testing Helpers: Create a custom macro for testing:

    // In a TestCase
    public function assertCreatedBy($model, $user) {
        $this->assertEquals($user->id, $model->created_by_id);
    }
    

Performance Considerations

  1. Eager Loading: Avoid N+1 queries when accessing createdBy:

    $posts = Post::with('createdBy')->get();
    
  2. Indexing: Add database indexes for frequent queries:

    $table->foreignId('created_by_id')->constrained()->index();
    
  3. Batch Updates: For bulk updates, use update() instead of looping:

    // Bad: N queries
    foreach ($posts as $post) {
        $post->update(['updated_by_id' => $user->id]);
    }
    
    // Good: 1 query
    Post::whereIn('id', $postIds)->update(['updated_by_id' => $user->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.
nasirkhan/laravel-sharekit
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony