Laravel package by MuhammadObadaa
Scan, inspect, and (optionally) force‐delete Eloquent models along with their HasOne/HasMany branches—without relying on database‐level cascade or restrict rules.
OnDelete, you can walk through a model’s HasOne/HasMany relations (to any depth), get a nested “tree” of related IDs, check whether a model is safe to delete, or forcibly delete the entire sub‐tree in one shot.
Require the package via Composer:
composer require mhdobd/eloquent-relation-guard
Publish the configuration file:
php artisan vendor:publish --provider="EloquentRelation\Guard\EloquentRelationGuardServiceProvider" --tag="config"
This will copy config/eloquent-relation-guard.php
into your application’s config/
directory.
-
Use the Trait in Your Model Add the
HasRelationalDependencies
trait to any Eloquent model you want to protect/scan.use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use EloquentRelation\Guard\Traits\HasRelationalDependencies; class Post extends Model { use HasRelationalDependencies; /** * By default, all HasOne/HasMany relations will be scanned. * If you want to limit or specify nested branches, define: */ protected array $scanRelations = [ 'comments', // only scan Post::comments() 'comments.replies', // also scan replies under each comment 'tags', // scan Post::tags() (if tags is a HasMany relationship) '*' // or simply, add all first-level relations ]; // Type hint (mention the return type of) each HasOne/HasMany relation method public function comments(): HasMany { return $this->hasMany(Comment::class); } }
-
Check if a Record Can Be Deleted
$post = Post::find(42); if ($post->canBeSafelyDeleted()) { // no related HasOne/HasMany records exist $post->delete(); } else { // there are related records—perhaps alert the user // so you can alert the user with detailed related relations using $post->relationStructure }
-
Get the Full Relation “Tree” (with IDs)
$post = Post::find(42); // Pass a depth (integer) to limit how many levels deep to scan. // Use -1 for no depth limit, only memory and time one. $tree = $post->relationStructure(depth:2); // $tree will look like: // [ // 'comments' => [ // 'ids' => [10, 11, 12], // 'model' => 'App\Models\Comment', // 'nested'=> [ // 'replies' => [ // 'ids' => [101, 102], // 'model' => 'App\Models\CommentReply', // 'nested'=> [ /* … */ ], // ], // ], // ], // 'tags' => [ // 'ids' => [5, 6], // 'model' => 'App\Models\Tag', // 'nested'=> [], // ], // ]
-
Force‐Delete a Model and All Related Records
$post = Post::find(42); $deletedCount = $post->forceCascadeDelete(); // This will delete all HasOne/HasMany descendants (ignoring DB foreign‐key rules) // and then delete the Post itself. $deletedCount is the total number of records removed.
-
Console Command:
record:tree
You can visualize a model’s relation tree (with IDs) from the CLI:php artisan record:tree Post 42 2
Post
: The model class name, it should be located inapp/models/
directory42
: ID of the record to inspect2
: Depth (how many nested levels to scan; use-- -1
for unlimited)
Example Output:
Relation Tree for App\Models\Post (ID: 42) | Depth: 2 ├── comments (App\Models\Comment): [10, 11, 12] │ └── replies (App\Models\CommentReply): [101, 102] └── tags (App\Models\Tag): [5, 6]
for more details check the Documentation
- Add support for soft deletes (detecting
deleted_at
and deciding whether to include or ignore soft‐deleted records). - Support morph relations along with HasOne and HasMany relations.
- Allow configurable thresholds for maximum nodes/depth before aborting the scan.
- Add event hooks (e.g.,
beforeDeleteGuarded
,afterDeleteGuarded
) so users can tap into the delete process. - Provide Laravel Nova/Filament integrations for visual “Are you sure?” modals.
- Mark visited classes when DFS over them so it can avoid cyclic database relations.
- Write feature tests and include sample migrations/seeders.
- Add Complexity Details in documentation file.
- Optimize Time, Memory, and DB Query complexity over core package logic implementation.
If you discover bugs, have feature requests, or want to contribute code, please use the GitHub issue tracker:
Issues & Contributions: https://github.com/MuhammadObadaa/eloquent-relation-guard/issues
Feel free to fork the repository, open a PR, and follow these basic guidelines:
- Fork the repo and create a new branch for your feature/fix.
- Write at least one test (where applicable) demonstrating the expected behavior.
- Update
CHANGELOG.md
andREADME.md
if you add or change functionality. - Submit a pull request—describe what you changed and why.
Eloquent Relation Guard package is open source, licensed under MIT. Feel free to use, modify, and redistribute.