Skip to content

Lifecycle Hooks

Every CRUD operation supports before/after hooks. Define them on your model or override them in your controller.

Available Hooks

OperationBefore HookAfter Hook
store()beforeCreate(Model)afterCreate(Model)
update()beforeUpdate(Model)afterUpdate(Model)
destroy() / delete()beforeDelete(Model)afterDelete(Model)
changeStatus()beforeStatusChange(Model)afterStatusChange(Model)
updateColumn()beforeColumnUpdate(Model)afterColumnUpdate(Model)
restore()beforeRestore(Model)afterRestore(Model)
permanentDelete()beforeForceDelete(Model)afterForceDelete(Model)

Model-Level Hooks

Define the methods directly on your model. The controller checks method_exists() before calling:

php
class Post extends Model
{
    public function beforeCreate(): void
    {
        $this->slug = Str::slug($this->name);
    }

    public function afterCreate(): void
    {
        if (request()->filled('tag_ids')) {
            $this->tags()->sync(request()->input('tag_ids'));
        }
    }

    public function beforeUpdate(): void
    {
        $this->slug = Str::slug($this->name);
    }

    public function afterUpdate(): void
    {
        if (request()->filled('tag_ids')) {
            $this->tags()->sync(request()->input('tag_ids'));
        }
    }

    public function beforeDelete(): void
    {
        // Clean up related data before deletion
    }

    public function afterDelete(): void
    {
        // Log deletion, send notification, etc.
    }

    public function beforeStatusChange(): void { }
    public function afterStatusChange(): void { }

    public function beforeColumnUpdate(): void { }
    public function afterColumnUpdate(): void { }

    public function beforeRestore(): void { }
    public function afterRestore(): void { }

    public function beforeForceDelete(): void { }
    public function afterForceDelete(): void { }
}

Controller-Level Hooks

Override hooks in your controller. This completely replaces the model-level hook — the model method is no longer called:

php
class PostController extends BaseController
{
    protected function afterCreate(Model $model): void
    {
        // This replaces $model->afterCreate()
        Notification::send($admins, new PostCreated($model));
        Cache::forget('posts.count');
    }

    protected function beforeDelete(Model $model): void
    {
        // Called before both soft delete and force delete
        Log::info("Deleting post: {$model->id}");
    }
}

Transaction Safety

All hooks run inside a database transaction. If any hook throws an exception, the transaction is rolled back:

beginTransaction()
  → beforeCreate($model)
  → $model->save()
  → afterCreate($model)
commit()

// If any step throws:
rollBack()

This applies to store, update, destroy, bulk delete, changeStatus, updateColumn, restore, and permanentDelete.

Released under the MIT License.