Duplicating Records with replicate() - Laravel

 How to use replicate() in Laravel to duplicate records

Duplicating Records with replicate() - Laravel

Do you remember when you needed to create a "Duplicate" or "Clone" button in your web app?

No matter what it was – duplication of a complex invoice, cloning of a draft for a blog post, creation of a duplicate product entry on a marketplace, making a template from an existing entry – data duplication is one of the most requested features.

Without Laravel, you would have to retrieve the entry and read each and every field manually in order to create a new model array. It is not only time-consuming and ineffective but will break whenever you add another column to your database table.

Replicate() function allows you to do all that with just one line of code! It is pretty straightforward and here is the short explanation of how it works.

The Traditional Approach (What NOT to Do)

Imagine you want to copy an existing blog post so an editor can use it as a template. Without replicate(), your code usually looks like this:

$originalPost = Post::find(1);

// Not recommended and breaks if you add new database columns later!
$newPost = new Post([
    'title' => $originalPost->title . ' (Copy)',
    'content' => $originalPost->content,
    'category_id' => $originalPost->category_id,
    'author_id' => $originalPost->author_id,
    'status' => 'draft',
]);

$newPost->save();

If your posts table has 20 columns, you will have to write 20 lines of repetitive code just to copy a record.

How replicate() Works

The replicate() method creates a blank-new, unsaved copy of your Eloquent model instance. It copies over all the attribute values from the original model except for:

  • The Primary Key (id)
  • The Timestamps (created_at and updated_at)

Because the id is left out, Eloquent treats the replicated object as a brand-new database entry waiting to be saved.

$originalPost = Post::find(1);

// Creates a fresh, unsaved copy in memory
$clonedPost = $originalPost->replicate();

// Save it to the database as a new row
$clonedPost->save();

That's it small and simple. One line to copy and one line save.

Step-by-Step Usage Guide

Step 1: Basic Replication & Modifying Attributes

When you duplicate a record, you almost always want to tweak a few fields before saving—like changing a status from "published" to "draft", or adding "(Copy)" to a title.

Since replicate() returns an unsaved model instance in memory, you can easily modify its properties before calling save():

$originalProduct = Product::find(10);

$newProduct = $originalProduct->replicate();

// Override specific attributes
$newProduct->title = $originalProduct->title . ' (Duplicate)';
$newProduct->sku = 'SKU-' . Str::random(8); // Unique SKU required
$newProduct->status = 'draft';

// Now persist to MySQL
$newProduct->save();

Step 2: Excluding Specific Attributes (The Except Parameter)

Sometimes your model contains fields that must be unique across your database (like a unique slug, uuid, or sku), or fields you simply don't want copied over.

Instead of manually clearing them after replicating, pass an array of attribute names directly into replicate():

// Pass an array of attributes to ignore during replication
$clonedPost = $originalPost->replicate([
    'slug',
    'views_count',
    'published_at'
]);

$clonedPost->title = 'Cloned Post Title';
$clonedPost->slug = Str::slug($clonedPost->title);
$clonedPost->save();

Here, slug, views_count, and published_at are skipped entirely during the cloning process.

Step 3: Cloning a Model Along with Its Relationships

What if your Post has multiple Tags or Comments attached to it, and you want to duplicate those relationships too?

replicate() only copies the main model's database row. To duplicate attached relationships, pair replicate() with Eloquent's relationship methods as shown below.

Duplicating a BelongsToMany (Many-to-Many) Relationship:

$originalPost = Post::with('tags')->find(1);

// 1. Replicate the main post
$newPost = $originalPost->replicate(['slug']);
$newPost->title = $originalPost->title . ' (Copy)';
$newPost->save();

// 2. Attach the same tags to the new post
$newPost->tags()->sync($originalPost->tags->pluck('id'));

Duplicating HasMany (One-to-Many) Relationships:

$originalInvoice = Invoice::with('items')->find(100);

// 1. Replicate main invoice
$newInvoice = $originalInvoice->replicate();
$newInvoice->invoice_number = 'INV-2026-002';
$newInvoice->save();

// 2. Replicate every line item on the invoice
foreach ($originalInvoice->items as $item) {
    $newItem = $item->replicate();
    $newItem->invoice_id = $newInvoice->id; // Assign to new invoice
    $newItem->save();
}

Real-World Controller Example

Here is how clean a controller action looks when implementing a "Duplicate Quiz" feature in an application.

public function duplicate(Quiz $quiz)
{
    // Replicate quiz metadata
    $newQuiz = $quiz->replicate(['slug']);
    $newQuiz->title = $quiz->title . ' (Copy)';
    $newQuiz->is_published = false;
    $newQuiz->save();

    return redirect()
        ->route('quizzes.edit', $newQuiz->id)
        ->with('success', 'Quiz duplicated successfully!');
}

Key Takeaways

  • replicate() copies attributes in memory without touching the original database row or copying the id / timestamps.
  • Modify before saving: You can freely tweak fields on the replicated instance before calling save().
  • Use the exclude array: Pass replicate(['slug', 'uuid']) to instantly strip unique constraints or counters.
  • Handle relationships manually: Remember that replicate() only duplicates the parent row; iterate or sync to handle related child models.
Thank you for reading this article 😊

For any query do not hesitate to comment 💬


Previous Post Next Post

Contact Form