shiftonelabs/laravel-cascade-deletes
Installation:
composer require shiftonelabs/laravel-cascade-deletes
Publish the config (optional, but recommended for customization):
php artisan vendor:publish --provider="ShiftOneLabs\LaravelCascadeDeletes\CascadeDeletesServiceProvider"
Basic Usage:
Extend your Eloquent model with \ShiftOneLabs\LaravelCascadeDeletes\CascadeDeletes:
use ShiftOneLabs\LaravelCascadeDeletes\CascadeDeletes;
class ParentModel extends Model
{
use CascadeDeletes;
}
Define Cascade Rules: In your model, define which relationships should cascade:
protected $cascadeDeletes = ['children', 'posts']; // Relationship names
First Use Case:
Delete a parent record, and all related records (as defined in $cascadeDeletes) will also be deleted:
$parent = ParentModel::find(1);
$parent->delete(); // Automatically deletes related records
$cascadeDeletes and let the package handle the rest.hasMany, belongsToMany, etc.).Use a closure to conditionally include/exclude relationships:
protected $cascadeDeletes = [
'posts' => function ($model) {
return $model->isActive(); // Only cascade if active
},
'comments' => true, // Always cascade
];
If using SoftDeletes, ensure the package is configured to handle soft deletes:
protected $cascadeSoftDeletes = ['children', 'posts']; // Soft-delete related models
Configure in config/cascade-deletes.php:
'soft_deletes' => true,
Handle polymorphic relationships by specifying the morphMap or using closures:
protected $cascadeDeletes = [
'images' => function ($model) {
return $model->images()->where('type', 'avatar');
},
];
Override the performCascadeDeletes method for custom logic:
protected function performCascadeDeletes()
{
// Custom logic before/after deletion
$this->logDeletion();
parent::performCascadeDeletes();
}
Use delete() on collections or query results:
ParentModel::where('status', 'active')->delete(); // Cascades for all matching records
Wrap deletions in transactions to ensure atomicity:
DB::transaction(function () {
$parent->delete(); // All cascading happens within the transaction
});
Listen for deleting or deleted events to hook into the cascade process:
public function boot()
{
static::deleting(function ($model) {
// Pre-deletion logic
});
static::deleted(function ($model) {
// Post-deletion logic (e.g., cleanup)
});
}
Use the package in API controllers to ensure cascading works as expected:
public function destroy(ParentModel $parent)
{
$parent->delete(); // Cascades automatically
return response()->noContent();
}
Parent has Children, Child has Parent) can cause infinite loops.protected $cascadeDeletes = ['children'];
protected $cascadeDeletesDepth = 1; // Limit recursion depth
config/cascade-deletes.php:
'soft_deletes' => true, // or false
'force_delete' => false, // Force hard delete even if soft deletes are enabled
withoutEvents() to skip event firing during bulk operations.morphMap is incomplete.$cascadeDeletes:
protected $cascadeDeletes = [
'images' => function ($model) {
return $model->images()->where('type', 'avatar')->get();
},
];
public function deleting($model)
{
// Avoid modifying $model->relationships here
}
Add debug logging to config/cascade-deletes.php:
'debug' => env('CASCADE_DELETES_DEBUG', false),
Check Laravel logs for cascade operations.
Verify config/cascade-deletes.php settings:
soft_deletesforce_deletedepth_limitexcluded_modelsdd()Temporarily add dd() to debug relationships:
protected function performCascadeDeletes()
{
dd($this->cascadeDeletes); // Inspect relationships
parent::performCascadeDeletes();
}
Override performCascadeDeletes or getCascadeDeletes:
protected function getCascadeDeletes()
{
$deletes = parent::getCascadeDeletes();
// Add/remove relationships dynamically
return $deletes;
}
Use closures to dynamically determine cascading:
protected $cascadeDeletes = [
'dynamic_relation' => function ($model) {
return $model->isAdmin() ? ['comments', 'reports'] : [];
},
];
Listen for cascade.deleting and cascade.deleted events:
Event::listen('cascade.deleting', function ($model, $relationship) {
// Custom logic before cascading
});
Extend the package to support non-Eloquent storage (e.g., MongoDB):
ShiftOneLabs\LaravelCascadeDeletes\CascadeDeletes traits.How can I help you explore Laravel packages today?