Download the PHP package tuzelko/yii2-softdelete without Composer
On this page you can find all versions of the php package tuzelko/yii2-softdelete. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download tuzelko/yii2-softdelete
More information about tuzelko/yii2-softdelete
Files in tuzelko/yii2-softdelete
Package yii2-softdelete
Short Description Soft delete extension for Yii2 framework
License MIT
Informations about the package yii2-softdelete
Yii2 Soft-Delete extension
Soft-delete extension for the Yii2 framework.
Adds soft-delete (and restore) behaviour to any ActiveRecord model via a single PHP trait, with an accompanying query class that automatically hides deleted records from all queries.
Features
- Four column strategies — Unix timestamp (
int), DB-native datetime, boolean flag, or zero-based timestamp (UNIQUE-index friendly) - Automatic query scope — deleted records are invisible by default; opt in with
withDeleted()/onlyDeleted() - Instance methods —
softDelete(),hardDelete(),restore(),isSoftDeleted() - Configurable
delete()— routes tosoftDelete()orhardDelete()depending ondefaultDeleteMethod() - Bulk methods —
softDeleteAll(),hardDeleteAll(),restoreAll(),updateAll()(all scope-aware) - Configurable
deleteAll()— same routing asdelete() - Events —
beforeSoftDelete,afterSoftDelete,beforeRestore,afterRestore - Multi-database — MySQL, PostgreSQL, SQLite, SQL Server, Oracle
- Zero configuration — sensible defaults, override only what you need
Requirements
- PHP >= 8.2
- yiisoft/yii2 ~2.0
Installation
Quick start
1. Add the column to your migration
2. Apply the trait to your model
That's it. Post::find() now returns only non-deleted records, and $post->delete() soft-deletes instead of hard-deletes.
Column strategies
Override softDeleteColumn() and softDeleteType() when the defaults do not fit your schema.
| Constant | Column value when deleted | Column value when restored |
|---|---|---|
TYPE_TIMESTAMP_INT (default) |
time() (Unix timestamp) |
NULL |
TYPE_TIMESTAMP_DB |
NOW() / datetime('now') / etc. |
NULL |
TYPE_BOOL |
1 |
0 |
TYPE_TIMESTAMP_INT_ZERO |
time() (Unix timestamp) |
0 |
TYPE_TIMESTAMP_INT_ZERO keeps the deletion timestamp like TYPE_TIMESTAMP_INT, but stores 0 instead of NULL for non-deleted rows. Use it when the column must be part of a UNIQUE index: most engines exclude NULL from uniqueness checks, so a plain timestamp column lets duplicate "live" rows slip through — 0 does not.
Instance methods
delete() is a routing method — by default it calls softDelete(). See Default delete routing to change this.
Deprecated:
forceDelete()is a deprecated alias forhardDelete().
Query scopes
Bulk operations
deleteAll() is a routing method — by default it calls softDeleteAll(). See Default delete routing to change this.
Deprecated:
forceDeleteAll()is a deprecated alias forhardDeleteAll().Auto-scope behaviour:
softDeleteAll(),updateAll(), andrestoreAll()automatically add a "not deleted" (or "deleted") condition unless your$conditionalready references the soft-delete column. This prevents double-applying the scope when you target records explicitly.
Default delete routing
defaultDeleteMethod() controls what delete() and deleteAll() do. Override it in your model to change the behaviour:
| Constant | delete() behaviour |
deleteAll() behaviour |
|---|---|---|
DELETE_METHOD_SOFT (default) |
calls softDelete() |
calls softDeleteAll() |
DELETE_METHOD_HARD |
calls hardDelete() |
calls hardDeleteAll() |
DELETE_METHOD_DISABLED |
throws NotSupportedException |
throws NotSupportedException |
Relations
Because SoftDeleteTrait overrides find() to return a SoftDeleteActiveQuery, the soft-delete scope is automatically applied to every relation that points to a soft-delete-enabled model — including eager loading via with() and join-based loading via joinWith().
Declaring relations
Eager loading with with()
JOIN-based loading with joinWith()
Both models' soft-delete scopes are applied automatically. The condition for each model is placed in the JOIN's ON clause (not WHERE), which preserves correct LEFT JOIN semantics: a user with no active posts still appears with NULL post columns rather than disappearing.
Column names are always table-qualified (post.deleted_at), so joining two tables that both have a soft-delete column never produces an "ambiguous column" SQL error.
The relation callback works the same as with with():
Events
All four events receive a yii\base\ModelEvent. Setting $event->isValid = false in a before* handler cancels the operation.
| Constant | When |
|---|---|
SoftDeleteTrait::EVENT_BEFORE_SOFT_DELETE |
Before softDelete() writes to the DB |
SoftDeleteTrait::EVENT_AFTER_SOFT_DELETE |
After softDelete() succeeds |
SoftDeleteTrait::EVENT_BEFORE_RESTORE |
Before restore() writes to the DB |
SoftDeleteTrait::EVENT_AFTER_RESTORE |
After restore() succeeds |
hardDelete() fires the standard Yii2 ActiveRecord::EVENT_BEFORE_DELETE / EVENT_AFTER_DELETE events.
Performance
Add an index on the soft-delete column so that the automatic scope does not cause a full-table scan:
Without the index every find(), softDeleteAll(), updateAll(), and restoreAll() call will scan the whole table once it grows large.
Cascade soft-deletes
Soft-deleting a parent record does not automatically soft-delete its children. If you need cascading behaviour, implement it in the afterSoftDelete hook:
String conditions and auto-scope
softDeleteAll(), updateAll(), and restoreAll() automatically add a soft-delete scope unless your $condition already references the soft-delete column. This detection works for array conditions only. Plain SQL strings are not inspected.
If you pass a raw string that already targets the soft-delete column, wrap it in an array to prevent the scope from being added twice:
Running tests
Tests run inside Docker (PHP 8.3 + SQLite) with no local setup required.
License
MIT — see LICENSE.