Installation:
composer require digitalcloud/laravel-blameable
For Laravel <5.5, manually register DigitalCloud\Blameable\BlameableServiceProvider in config/app.php.
Publish Config (optional, but recommended for customization):
php artisan vendor:publish --provider="DigitalCloud\Blameable\BlameableServiceProvider" --tag="config"
This generates config/blameable.php with default column names (created_by, updated_by, deleted_by) and model mappings.
Apply to a Model:
Use the Blameable trait in your Eloquent model:
use DigitalCloud\Blameable\Blameable;
class Post extends Model
{
use Blameable;
}
First Use Case:
Authenticate a user (e.g., auth()->user()), then create/update a model. The package auto-populates created_by, updated_by, or deleted_by based on the authenticated user.
Automatic Tracking:
created_by, updated_by, and deleted_by to the authenticated user (via Auth::user()).Model-Specific Configuration:
config/blameable.php:
'column_names' => [
'createdByAttribute' => 'author_id',
'updatedByAttribute' => 'last_modified_by',
],
Admin instead of User):
'models' => [
'admin' => \App\Models\Admin::class,
],
Manual Overrides: Force a specific user for an operation:
$post = new Post();
$post->forceFillUser($user)->save(); // Manually set creator/updater.
Soft Deletes:
If using SoftDeletes, deleted_by is auto-populated on delete():
$post->delete(); // Sets `deleted_by` to authenticated user.
Query Scopes: Filter models by creator/updater:
Post::createdBy($user)->get();
Post::updatedBy($user)->get();
auth middleware to ensure users are authenticated before blameable operations.creating, updating, or deleted events to log or audit changes:
Post::created(function ($post) {
Log::info("Post {$post->id} created by {$post->created_by}");
});
laravel-api packages to expose blameable fields in responses:
return new PostResource($post->load('user')); // Show creator details.
Authentication Dependency:
Auth::user(). If no user is authenticated, blameable fields will be null.config(['blameable.default_user' => 1]); // Fallback user ID.
Column Name Conflicts:
created_by, the package will overwrite them.config/blameable.php or add fillable guards:
protected $fillable = ['title', 'content']; // Exclude blameable columns.
Soft Deletes + Blameable:
deleted_by only works with SoftDeletes. For hard deletes, manually set the field:
$post->forceDelete(); // Won't auto-set `deleted_by`.
$post->deleted_by = auth()->id();
$post->delete();
Model Caching:
Model::newQuery()->get()), blameable attributes may not update in real-time.Auth::user() returns the expected user:
dd(auth()->user()); // Debug during operations.
DB::enableQueryLog();
$post->save();
dd(DB::getQueryLog());
config/blameable.php is correctly published and loaded.Custom User Resolution: Override the user resolver in the trait:
use DigitalCloud\Blameable\Concerns\ResolvesUser;
class Post extends Model
{
use Blameable, ResolvesUser;
protected function resolveUser()
{
return User::find(1); // Custom logic.
}
}
Dynamic Column Names: Use accessors to dynamically compute blameable fields:
public function getCreatedByAttribute($value)
{
return User::find($value)?->name ?? 'Anonymous';
}
Batch Operations: For bulk updates, manually set blameable fields:
Post::where('status', 'draft')->update([
'updated_by' => auth()->id(),
'status' => 'published',
]);
Testing: Mock the authenticated user in tests:
$this->actingAs($user);
$post = Post::create([...]); // `created_by` will be `$user->id`.
How can I help you explore Laravel packages today?