<p>I'm going to look pretty dumb if somebody drops a one-line answer down the line, but here goes: AFAIK, unfortunately, "cloning" an element (e.g. an EntryModel) isn't that simple.</p>

<p>For one, <code>$model-&gt;getContent()</code> will pull the entry's <a href="https://craftcms.stackexchange.com/a/4487/1098">ContentModel</a>, which basically contains all the custom fields that are stored in the <code>craft_content</code> table for your particular entry. Unfortunately, certain fieldtypes (e.g. Matrix, relational fields such as Assets, Categories, Entries etc) don't actually store their content in the <code>craft_content</code> table, so their values in the ContentModel will be <code>null</code>. To get to those values, you'll basically have to loop over your original entry's FieldLayout, and pull each field's actual value. You could then apply those values to your new EntryModel's <code>setContentFromPost()</code> method, but remember that relational fields (such as Assets and Entries) should be set as an array of IDs, not an ElementCriteriaModel (which is what you'll get back when you pull the field using <code>$entry-&gt;$someFieldHandle</code> or <code>$entry-&gt;getFieldValue('someFieldHandle')</code>.</p>

<p>If the entry you want to clone has Matrix fields, that's another can of worms. Matrix blocks are actually elements in themselves, and you'll basically need to follow the same pattern as with cloning the entry itself, in order to properly "clone" the blocks.</p>

<p>Unfortunately, I don't have a full, working example typed out, but here's some non-tested boilerplate code to get you started (I conveniently skipped the Matrix part, but there's a link at the bottom which may be helpful):</p>

<pre><code>$newModel = $model-&gt;copy();
$newModel-&gt;id = null;

// Loop through the original model's custom field values, and set them to the new model; account for relational fields
$customFieldValues = [];
foreach ($model-&gt;getFieldLayout()-&gt;getFields() as $fieldLayoutField) {
    $field = $fieldLayoutField-&gt;getField();
    $fieldType = $field-&gt;type;
    $fieldHandle = $field-&gt;handle; 
    $fieldValue = null;
    switch ($fieldType) {
        case 'Assets': case 'Entries': case 'Categories': case 'Tags': case 'Users':
            $fieldValue = $model-&gt;$fieldHandle-&gt;ids();
            break;
        case 'Matrix':
            // Whoa, Nelly
            break;
        default:
            $fieldValue = $model-&gt;$fieldHandle;
    }
    if ($fieldValue) {
        $customFieldValues[$fieldHandle] = $fieldValue;
    }
}
$newModel-&gt;setContentFromPost($customFieldValues);

// Save the new entry
$success = craft()-&gt;entries-&gt;saveEntry($newModel);
</code></pre>

<p>Note that if you need this to work for all element types, you may get away with calling <code>craft()-&gt;elements-&gt;saveElement($newModel)</code> at the end, instead of the <code>EntriesService::saveEntry</code> method. Otherwise, you'll need to check the <code>$newModel-&gt;elementType</code> property, and call the appropriate service's method for saving the element.</p>

<p>Finally, here are some other SE threads that may be of interest:</p>

<p><a href="https://craftcms.stackexchange.com/a/4552/1098">Getting all content, including Matrix fields from an EntryModel</a><br>
<a href="https://craftcms.stackexchange.com/questions/14157/how-to-get-all-prepped-field-values-from-an-entry-indexed-by-field-handle?rq=1">How to get all (prepped) field values from an entry, indexed by field handle</a><br>
<a href="https://craftcms.stackexchange.com/a/11781/1098">Duplicating Matrix fields with content from another locale</a></p>

CC BY-SA 3.0
2016-09-08T23:07:18.773Z
2016-09-08T23:07:18.773Z
2017-04-13T12:50:59.930Z
Mats Mikkel Rummelhoff
<p><code>$clonedEntry = Craft::$app-&gt;getElements()-&gt;duplicateElement($entry);</code></p>
<p>Not sure if you have to save it afterward or not because in my code I'm altering one field on it after duplication and therefore I'm saving it anyway, and I'm too lazy to test if it's necessary or not if you're leaving it as-is.</p>

CC BY-SA 4.0
2022-04-08T20:32:49.453Z
2022-04-08T20:32:49.453Z
Brimby
<p>Duplicating models is easy if you do it from the edit view, where you can just omit the ID and pass it along to <code>save()</code>.</p>

<p>But how would I go about doing that programmatically without having a POST array to work with?</p>

<p>I tried removing the ID from the model, before I pass it to <code>save()</code>, in the end I had two identical entries in the database, but I could only access the new one when finding records by ID.<br>
The original or any subsequent "original" items I clone from become unavailable even though they're in the database.<br>
My guess is that the Content model just changes its ownership to the newly created entry and that causes this to happen.</p>

<p>I also tried <code>$model-&gt;copy()</code> and removing the ID, and that held the same results.</p>

<p>I tried copying the <code>$model-&gt;getContent()</code> and removing its ID, then using <code>$model-&gt;setContent($clonedContent)</code>. This, at least, didn't prevent me from being able to access the original entry, but the content was never copied (all of my custom field data).</p>

<p>So how should go about this?<br>
Any help greatly appreciated!</p>

<control-panel><elementtype><models>
How to duplicate an element type model with content?
# How to duplicate an element type model with content?

(Asked by: username_0 on 2016-09-07)

Duplicating models is easy if you do it from the edit view, where you can just omit the ID and pass it along to `save()`.

But how would I go about doing that programmatically without having a POST array to work with?

I tried removing the ID from the model, before I pass it to `save()`, in the end I had two identical entries in the database, but I could only access the new one when finding records by ID.  
The original or any subsequent "original" items I clone from become unavailable even though they're in the database.  
My guess is that the Content model just changes its ownership to the newly created entry and that causes this to happen.

I also tried `$model->copy()` and removing the ID, and that held the same results.

I tried copying the `$model->getContent()` and removing its ID, then using `$model->setContent($clonedContent)`. This, at least, didn't prevent me from being able to access the original entry, but the content was never copied (all of my custom field data).

So how should go about this?  
Any help greatly appreciated!

**Tags:** control-panel, elementtype, models


---

## 2 answers

### Answer by username_1 on 2016-09-08. Score: 3 | Accepted answer

I'm going to look pretty dumb if somebody drops a one-line answer down the line, but here goes: AFAIK, unfortunately, "cloning" an element (e.g. an EntryModel) isn't that simple.
For one, $model->getContent() will pull the entry's ContentModel, which basically contains all the custom fields that are stored in the craft_content table for your particular entry. Unfortunately, certain fieldtypes (e.g. Matrix, relational fields such as Assets, Categories, Entries etc) don't actually store their content in the craft_content table, so their values in the ContentModel will be null. To get to those values, you'll basically have to loop over your original entry's FieldLayout, and pull each field's actual value. You could then apply those values to your new EntryModel's setContentFromPost() method, but remember that relational fields (such as Assets and Entries) should be set as an array of IDs, not an ElementCriteriaModel (which is what you'll get back when you pull the field using $entry->$someFieldHandle or $entry->getFieldValue('someFieldHandle').
If the entry you want to clone has Matrix fields, that's another can of worms. Matrix blocks are actually elements in themselves, and you'll basically need to follow the same pattern as with cloning the entry itself, in order to properly "clone" the blocks.
Unfortunately, I don't have a full, working example typed out, but here's some non-tested boilerplate code to get you started (I conveniently skipped the Matrix part, but there's a link at the bottom which may be helpful):
$newModel = $model->copy();
$newModel->id = null;

// Loop through the original model's custom field values, and set them to the new model; account for relational fields
$customFieldValues = [];
foreach ($model->getFieldLayout()->getFields() as $fieldLayoutField) {
    $field = $fieldLayoutField->getField();
    $fieldType = $field->type;
    $fieldHandle = $field->handle; 
    $fieldValue = null;
    switch ($fieldType) {
        case 'Assets': case 'Entries': case 'Categories': case 'Tags': case 'Users':
            $fieldValue = $model->$fieldHandle->ids();
            break;
        case 'Matrix':
            // Whoa, Nelly
            break;
        default:
            $fieldValue = $model->$fieldHandle;
    }
    if ($fieldValue) {
        $customFieldValues[$fieldHandle] = $fieldValue;
    }
}
$newModel->setContentFromPost($customFieldValues);

// Save the new entry
$success = craft()->entries->saveEntry($newModel);

Note that if you need this to work for all element types, you may get away with calling craft()->elements->saveElement($newModel) at the end, instead of the EntriesService::saveEntry method. Otherwise, you'll need to check the $newModel->elementType property, and call the appropriate service's method for saving the element.
Finally, here are some other SE threads that may be of interest:
Getting all content, including Matrix fields from an EntryModel
How to get all (prepped) field values from an entry, indexed by field handle
Duplicating Matrix fields with content from another locale


---

### Answer by username_2 on 2022-04-08. Score: 1

`$clonedEntry = Craft::$app->getElements()->duplicateElement($entry);`

Not sure if you have to save it afterward or not because in my code I'm altering one field on it after duplication and therefore I'm saving it anyway, and I'm too lazy to test if it's necessary or not if you're leaving it as-is.


---

