Installation:
composer require neurony/laravel-duplicate
Publish the config file (if needed):
php artisan vendor:publish --provider="Neurony\Duplicate\DuplicateServiceProvider"
Basic Usage:
use Neurony\Duplicate\Facades\Duplicate;
$original = App\Models\Post::find(1);
$duplicate = Duplicate::duplicate($original);
First Use Case:
Clone a Post with its comments (hasMany) and author (belongsTo):
$post = App\Models\Post::find(1);
$clonedPost = Duplicate::duplicate($post, [
'comments' => true, // Duplicate related comments
'author' => false, // Skip duplicating author (avoid circular refs)
]);
config/duplicate.php for default behaviors (e.g., excluded fields, relationship handling).duplicating or duplicated.Basic Duplication:
$duplicate = Duplicate::duplicate($model);
hasOne, hasMany, belongsTo, and belongsToMany relationships.morph* relationships by default (configure via config/duplicate.php).Selective Relationship Duplication:
$duplicate = Duplicate::duplicate($model, [
'relationships' => ['comments', 'tags'], // Only duplicate these
'exclude' => ['deleted_at'], // Skip soft-deletes
]);
Custom Field Handling:
Duplicate::duplicate($model, [
'custom' => [
'slug' => function ($originalSlug) {
return "copy-of-{$originalSlug}";
},
],
]);
Batch Duplication:
$ids = [1, 2, 3];
Duplicate::duplicateMany(App\Models\Post::find($ids), [
'relationships' => ['comments'],
]);
Service Layer: Encapsulate duplication logic in a service class to centralize configurations:
class PostDuplicator {
public function duplicateWithAssets(Post $post) {
return Duplicate::duplicate($post, [
'relationships' => ['comments', 'attachments'],
'custom' => ['slug' => fn($s) => "copy-{$s}"],
]);
}
}
Admin Panels: Useful for "Clone" buttons in backends (e.g., Nova, Filament). Example for Filament:
use Neurony\Duplicate\Facades\Duplicate;
public function duplicate(Post $record) {
return Duplicate::duplicate($record);
}
Seeding: Duplicate seed data with relationships:
$originalUser = User::factory()->create();
$duplicateUser = Duplicate::duplicate($originalUser, [
'relationships' => ['posts', 'roles'],
]);
Testing: Reset duplicated models in tests:
public function tearDown(): void {
Duplicate::duplicateMany(User::all())->each->delete();
parent::tearDown();
}
Circular References:
User with a belongsTo Company and vice versa causes infinite loops.Duplicate::duplicate($user, ['exclude_relationships' => ['company']]);
Polymorphic Relationships:
morph* relationships are skipped by default. Enable with:
'config/duplicate.php':
'morph_relationships' => true,
Auto-Increment IDs:
Duplicate::duplicate($model)->fresh()->setAttribute('id', null)->save();
Timestamps:
custom:
'custom' => [
'created_at' => now(),
'updated_at' => now(),
],
Soft Deletes:
Duplicate::duplicate($model)->forceDelete();
Event Conflicts:
duplicating or duplicated events trigger side effects (e.g., notifications), disable them:
Duplicate::duplicate($model, ['events' => false]);
Log Duplication:
Enable debug mode in config/duplicate.php:
'debug' => env('DUPLICATE_DEBUG', false),
Logs appear in storage/logs/laravel.log.
Check Relationships: Verify relationships are loaded before duplication:
$model->load(['comments', 'author']); // Ensure eager-loaded
Validate Config: Test with a minimal model first:
$simpleModel = new class extends Model {};
Duplicate::duplicate($simpleModel); // Confirm no errors
Custom Duplicator: Extend the core logic by binding your own duplicator:
Duplicate::extend(function ($duplicator) {
$duplicator->afterDuplicate(function ($original, $duplicate) {
// Post-duplication logic (e.g., log, notify)
});
});
Override Defaults: Modify the config file to change global behavior (e.g., default excluded fields):
'exclude' => [
'id',
'uuid',
'deleted_at',
'created_at',
'updated_at',
],
Add New Relationship Types: If using custom relationship types, patch the duplicator:
Duplicate::extend(function ($duplicator) {
$duplicator->addRelationshipHandler('customMany', function ($original, $duplicate, $relationship) {
// Custom logic for 'customMany' relationships
});
});
Hook into Events: Listen for duplication events to add pre/post-processing:
event(new Duplicating($original, $duplicate));
event(new Duplicated($original, $duplicate));
Batch Relationship Loading: Load relationships in chunks for large datasets:
$model->loadMissing(['comments' => function ($query) {
$query->limit(100);
}]);
Disable Events for Bulk: Skip events during batch operations:
Duplicate::duplicateMany($models, ['events' => false]);
Queue Duplication: Offload heavy duplication to queues:
Duplicate::duplicate($model)->onQueue('duplicates');
How can I help you explore Laravel packages today?