Migrating the Drupal way. Part I: creating a node.
by Kevin Hankens
Update: Acquia has released a great migration whitepaper to help you get ready to move to Drupal.
My position with Acquia will find me helping out with a lot of migrations and upgrades. I'm going to embark on a multiple-part blog to discuss some of the common techniques that I use when moving clients to Drupal.
Migrating to Drupal can seem intimidating if you already maintain a database-driven website. However, populating a Drupal site with your current content might be easier than you think. Whether you are migrating from a popular CMS or a fully custom application, you can easily use Drupal modules to mimic your current data structures and migrate your data using a simple custom PHP script. I should note that while there are several different methods to accomplish this task, this happens to be my favorite.
When interacting with Drupal, it's a good idea to do things the Drupal way. Fortunately, Drupal core allows you to bootstrap Drupal and use all of its API functionality outside of a normal Drupal instance. For yours truly, learning about this has been a godsend because it provides a fast, simple way to migrate data.
Creating a basic node
When writing an import script, you will need to bootstrap Drupal to use the API functions. Using drupal_bootstrap($phase), you can load Drupal up to a certain loading phase by designating a $phase argument. The value of $phase allows you to specifically load the site configuration, database layer, modules and other requisite functionality. For our purposes, we will use drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL) to make sure that we have access to the whole API.
Note: Make sure that you create this script in the root of your Drupal installation.
// Bootstrap Drupal
For a simple example, we will create a basic node object and save it in our Drupal database using node_save().
// Construct the new node object.
$node = new stdClass();
// Your script will probably pull this information from a database.
$node->title = "My imported node";
$node->body = "The body of my imported node.\n\nAdditional Information";
$node->type = 'story'; // Your specified content type
$node->created = time();
$node->changed = $node->created;
$node->status = 1;
$node->promote = 1;
$node->sticky = 0;
$node->format = 1; // Filtered HTML
$node->uid = 1; // UID of content owner
$node->language = 'en';
// If known, the taxonomy TID values can be added as an array.
$node->taxonomy = array(2,3,1,);
Creating more complex nodes
The script above will create a new node with a title and body that is published and promoted to the homepage. However, the process becomes more slightly more complicated if you have more data than simple title and body fields. The CCK module is a popular method to extend your nodes by adding any number of custom fields. When Drupal displays your content, CCK adds your custom fields to the node object using hook_nodeapi(). Luckily, you can replicate this by adding your own fields in the import script. So, how can you find out the structure of these fields? One really easy method is to use the Devel module.
Using the Devel module
The Devel module is a great way to see, among other things, the structure of the node object which is invaluable in this case. After installing the module and viewing a node you will see new tabs: Dev load and Dev render. Click the Dev load tab, then click the "... (Object) stdClass" header to expand the node object definition. Here you will find some familiar data like nid, type, etc. Near the bottom, you will see some other definitions that begin with "field_". These should resemble the CCK fields that you created for your node type.
Depending on your CCK definitions, the assignments in your import script might look like one of the following:
$node->field_text_field['value'] = "value 1";
$node->field_text_field['value'] = "2nd value";
$node->field_nodereference['nid'] = 58;
Add these assignments to your import script and you will start to see the power of the Drupal API. Let's say you are migrating from another CMS with a number of related fields, categories, images, etc. You could expand this script to iterate through your old database and map all of the related elements to a corresponding node object. Execute your script, and all of your old data will now become Drupal data! The best part about using the API is that it takes care of all of everything from search indexing to path aliases and all of the other little things we might overlook.
Migrating to Drupal can seem like a daunting task, but when doing things the Drupal way it's quite straight forward. Whether you are planning a migration of 100 nodes or 100,000 nodes, proper scripting can make it seem like a breeze!