Duplicating a record with its relationships in Laravel

Article last updated:
Duplicating a record with its relationships in Laravel

Healty code bases need to be maintained. This includes removing packages which are no longer necessary.

Recently, we replaced a package that would let us duplicate a model's record with all its relations and, make changes to the new record.

To be clear, when we first discovered the neurony/laravel-duplicate package, it solved a problem in a time-constrained situation: We had to deliver a quick solution for record duplication and editing, all while refactoring our outdated internal CRM to our new, Laravel-based one. So using the package was a conscious choice at the time. But now, let's take a look at how we replaced this package with only a few lines of custom code.

The Solution

The request gets the customer and replicates it to a new record. That way, we get the ID which is necessary to clone the relationships we save the newly created record.

After that, we loop over the original customer model's relationships using an array of relationship names. When the record contains a relationship from our array we replicate the record and then assign the foreign_key column to the new primary_key of the replicated customer.

Using this method it doesn’t matter which type of relationship we used since we always apply the same column name for the foreign_key. Which is a requirement for this method.

public function duplicate(Customer $customer)

    $relationships = ['details', 'address', ...];

    $clone = $customer->replicate()->fill([
        // Make Changes to $fillable Attributes
    foreach ($relationships as $relationship) {
        if ($customer->$relationship) {
            $cloned_relation = $customer->$relationship->replicate();
            $cloned_relation->foreign_key = $clone->primary_key;
    return response()->json($clone, 201);

Nice to know

Model Event's support observing the replicating Event, even if it's not in the Documentation.

But on GitHub, you can find the event ↗.

Thanks for proofreading @tobias_grasse.