6

Seeing as moving entries between sections isn't supported (yet) through the Craft interface, I followed Brandon's answer for a workaround through the database.

I am moving entries from one structure to another; updating the sectionId in the database works fine and the entries are moving over without a problem.

However the issues start when I try and make some of the entries children to others that have also been moved.

I have tried both dragging the entry through the Structure view and setting the parent in the dropdown while editing the entry, but both are coming up with the same error:

An unknown error occurred.

And I am getting a 500 Internal Server error on this file

/index.php?p=admincp/api/structures/moveElement 500 (Internal Server Error)

Is this a bug within Craft, or have I missed out on some other information that needs to be updated in the database?

1 Answer 1

7

That’s a little more complicated, and at that point you’re going to be best off writing your own PHP code to do it.

Craft has a bootstrap file that makes it very easy to write custom PHP code without going to the trouble of writing a plugin, which is great for one-off tasks like this.

Just create a new file alongside your index.php file, called move_entry.php. Here’s what it should look like:

Craft 3

<?php


// ...
// copy contents of index.php here, except for the last `$app->run();` line
// ...


// Start a transaction in case anything goes south
$transaction = $app->db->beginTransaction();
try {
    // Fetch the entry you need to move
    $entry = \craft\elements\Entry::findOne(184);

    // Remove it from its old structure
    $oldSection = $entry->getSection();

    $record = \craft\records\StructureElement::findOne([
        'structureId' => $oldSection->structureId,
        'elementId' => $entry->id
    ]);

    if (!$record->deleteWithChildren()) {
        throw new \Exception('Could not delete the old structure node');
    }

    // Set the new sectionId and typeId on the entry
    $entry->sectionId = 2;
    $entry->typeId = 2;

    // Append it to the end of the new structure
    $newSection = $entry->getSection();

    if (!$app->structures->appendToRoot($newSection->structureId, $entry, 'insert')) {
        throw new \Exception('Could not insert the new structure node');
    }

    // Save the entry
    if (!$app->elements->saveElement($entry)) {
        throw new \Exception('Could not save the entry');
    }

    // Commit the transaction
    $transaction->commit();
} catch (\Exception $e) {
    // Undo whatever changes we already made
    $transaction->rollBack();
    throw $e;
}

echo 'success!';

Craft 2

<?php
namespace Craft;

// Initialize Craft without letting it take over the whole request
$app = require '../craft/app/bootstrap.php';

// Set Craft to Craft Personal so we don't get any errors about Client/Pro-only components not being available
$app->getInfo()->edition = 0;

// Start a transaction in case anything goes south
$transaction = $app->db->beginTransaction();
try
{
    // Fetch the entry you need to move
    $entry = $app->entries->getEntryById(184);

    // Remove it from its old structure
    $oldSection = $entry->getSection();

    $record = StructureElementRecord::model()->findByAttributes(array(
        'structureId' => $oldSection->structureId,
        'elementId'   => $entry->id
    ));

    if (!$record->deleteNode())
    {
        throw new Exception('Could not delete the old structure node');
    }

    // Set the new sectionId and typeId on the entry
    $entry->sectionId = 2;
    $entry->typeId = 2;

    // Append it to the end of the new structure
    $newSection = $entry->getSection();

    if (!$app->structures->appendToRoot($newSection->structureId, $entry, 'insert'))
    {
        throw new Exception('Could not insert the new structure node');
    }

    // Save the entry
    if (!$app->entries->saveEntry($entry))
    {
        throw new Exception('Could not save the entry');
    }

    // Commit the transaction
    $transaction->commit();

    echo 'success!';
}
catch (\Exception $e)
{
    // Undo whatever changes we already made
    $transaction->rollback();

    throw $e;
}

Plug the right entry/section/type IDs in there, point your browser to http://example.com/move_entry.php and you should be all set!

Warning: Make sure you never run this code for an entry that has any children in the structure, as its children will end up getting removed from the hierarchy.

10
  • Thanks for the detailed answer Brandon! But unfortunately I am getting the success message but the entry hasn't moved into the new structure.
    – Jamie Wade
    Oct 31, 2014 at 9:18
  • @JamieWade I had tested locally and it worked. Are you sure you put all the right IDs in there? If so, maybe just send a DB backup over to [email protected] Oct 31, 2014 at 12:03
  • Sorry Brandon, I've just run another test through and it seems to have worked fine and parenting is working as well, so thanks for that and sorry for taking up your time on this! One little thing however, if I run this on a parent entry, and then run it again on one of it's child entries (which have been moved to top level because the parent has gone), I get: "Fatal error: Call to a member function deleteNode() on a non-object in /vagrant/public/move_entry.php on line 25" Just a little thing as I will remember to move child entries first, but otherwise it's all good so thanks again.
    – Jamie Wade
    Oct 31, 2014 at 13:03
  • @JamieWade Ah yes, didn’t think about that. Calling deleteNode() will remove that entry and all of its decedents from the hierarchy, so yeah, only do this with entries that don’t have any children. Oct 31, 2014 at 13:27
  • Is it possible to move an Entry and it's children?
    – julzmon
    Nov 29, 2016 at 3:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.