How to upgrade a Drupal 6 website to Drupal 8 (how to try)

I’m currently trying to upgrade a Drupal 6 website to Drupal 8, but the process has been slow-going so far. I’ll explain the problems and workarounds in this article as I learn them.

So far I have been able to get a Drupal 6 website with 7,000+ nodes and 18,000+ URL aliases converted to the point that I can now see all of the old blog posts on the Drupal 8 site, and I’ve also started theming the Drupal 8 website.

VERY IMPORTANT UPDATE: As of May 11, 2016, my NEW/BEST approach is described in my Drupal 6 to Drupal 8 migration notes. That approach is newer and better than what I show below, though the information below is more expansive than those notes. In particular my new approach is to blow away both the full_html and full_html1 formats and create a new one. I also solve a problem related to Drupal Tags that I wasn’t aware of when I wrote this article.

Getting ready for the upgrade

The process of getting ready to upgrade a Drupal 6 website to Drupal 8 goes like this:

  • Make sure your Drupal 6 production website is updated to the latest version, Drupal 6.38 (that’s the last release of Drupal 6)
  • Make a backup of your production website, including a) the database, and b) the Drupal files.
  • Back up any additional production files you have that are not in Drupal subdirectories. For instance, I keep extra images in a /images folder on my site.
  • Copy the backups to another “Development” system where you will run the migration process.

On the Development (“Dev”) system, take these steps:

  • Unpack your Drupal 6 (D6) website under a web server. I use MAMP on a Mac system, so I put my old D6 site under /Applications/MAMP/htdocs.
  • Restore your D6 database on your Dev system. MySQL also runs under MAMP, so I create a database for the D6 site and then restore it.
  • Create an empty Drupal 8 (D8) database. Make sure you use a different MySQL username for this database (otherwise the migration process will fail, especially for larger sites.)
  • Unpack the Drupal 8.x files under your web server (i.e., under htdocs).

These next steps will vary a little depending on your platform:

  • On Unix systems, edit the /etc/hosts file to add entries for your websites. For the purposes of this article I’ll call them “drupal6” and “drupal8”.
  • Configure Apache, Nginx, or whatever web server you’re using so you have “drupal6” and “drupal8” entries for them. In my case I have two directories, /Applications/MAMP/htdocs/drupal6, and /Applications/MAMP/htdocs/drupal8.

Now start/restart your web server and MySQL instances. You should be able to access your drupal6 website without any problems, and if you go to a URL like http://drupal8:8888/ (under MAMP), you should see the Drupal 8 welcome/install page.

Clean up the Drupal 6 installation

This is a good time to clean up your Drupal 6 installation on your Dev/Test system. Here are a few things you can/should do:

  • Get rid of all currently-unapproved comments that you’re not going to approve, but haven’t deleted yet
  • Disable and remove all unused modules
  • Disable and remove all modules that won’t migrate to Drupal 8

The last two lines there are probably the most important things to do. I was surprised to find that even on my own D6 websites I had a few old modules installed that I was no longer using. In other words, this is an excellent time for a little housekeeping.

Install Drupal 8

Installing Drupal 8 is straightforward, for the most part you just have to follow the prompts and fill them in.

An initial issue is that you need to choose a “Standard” or “Minimal” installation. The Standard installs 40 Drupal modules, the Minimal installs only 10. I’ve gone through the installation process about ten times so far, and I have found that I prefer the Standard installation. The Minimal install did not port my url_aliases information, and that was a show-stopper for me. The Standard installation has its own problems, but I’ve been able to work around them so far.

The purpose of installing Drupal 8 in its own website is so that you can now port the Drupal 6 data into the Drupal 8 database, which is the next step of the process.

Upgrading Drupal 6 to Drupal 8

The next steps are as follows:

  • In your web browser, go to the D8 website, and click the “Extend” link in the menu.
  • On that page, scroll down and enable the “Migrate” modules. In Drupal 8.1.0 there are three of these, titled, “Migrate,” “Migrate Drupal,” and “Migrate Drupal UI.”
  • After enabling them, you’re told that they are experimental. Approve that, and then you’re taken to another page. I don’t remember the exact wording on this page, but there’s a link in the text that says something about running the migration process. Go ahead and click that link.
  • On the next form you need to enter information for your Drupal 6 website. You need to enter the information for your D6 database, and also specify the location of your D6 website files (such as /Applications/MAMP/htdocs/drupal6).

I think there’s a “Review” button on that page, so click that, then approve it on the following page. This will start the migration process. My current website has about 7,400 nodes and 18,000 URL aliases, and the process takes about 30 minutes when running on a Mac that is about two years old.

After the migration

Hopefully your migration process succeeded. If not, search https://www.drupal.org/project/issues/drupal and https://www.drupal.org to see if these are known problems.

The first big problem I had was that I tried to use the same MySQL username for both databases during the migration process. You can get away with this on smaller websites, but for a site of this side the migration process will fail if you try this (and your CPU use will go to 100%).

The second problem I had was that after the migration I could go to known blog post URLs on the D8 website, and I would see my page title, but no content. If I clicked the “Edit” link on that page I would see that my content was still there — I could edit it, but I couldn’t see it when I clicked “View.” This is a known problem that is discussed at this URL: https://www.drupal.org/node/2630578

The 16th comment on that page solved this problem for me. Basically you have to go into your Drupal 8 database and run this query:

UPDATE `node__body` SET `body_format`='full_html' WHERE `body_format`='full_html1';

For my Drupal 6 “Photo” content types, I also need to run this query:

UPDATE node__field_photo SET langcode='en';

After running this query, clear your caches (run drush cr).

The problem seems to be that the D8 Standard installation creates a type of full_html of its own, and this is in conflict with the full_html type that is used when you have a format type of “Full HTML” on your D6 site. The D8 installation doesn’t override that need, it creates the new name full_html1, and this is the problem.

You can confirm this by looking at the Edit form for any blog post on your D8 site that has (had) the “Full HTML” type. When you do that you’ll see an error message on that page that says something about a “null” type. I don’t have that page available right now, as I have fixed this problem on my site, but just look for “null” on that page and you’ll see an error message that explains the problem. The current solution to this problem is to run the SQL UPDATE query shown in comment 16 that I’ve shown above.

Drupal 6 to migration 8 bugs that are keeping me from upgrading

This is a list of bugs in the Drupal 6 to Drupal 8 migration process that are currently keeping me from migrating my D6 websites to D8 (as of May 5, 2016):

  • My D6 “Photo” content did not migrate properly to D8. The ImageCache files, and any references to those files, cannot be found. as this page states, “Images attached to Drupal 6 Image nodes, and files attached with File fields do not get migrated.”
  • My old sites used Views extensively, and as this page states, “Views are not yet migrated.”

There may be more problems than those, but I can’t get past those at the moment, so I can’t tell you about other problems.

This major bug is solved manually:

As a minor bug, the migration process defaults the Timezone to “Europe/London.”

Fix all “full_html1” problems

Other Drupal users may not need this fix, and I know that Drupal developers are working on this problem, but I have also run these queries to fix all full_html1 format problems in the database:

UPDATE block_content__body SET body_format='full_html' WHERE body_format='full_html1';
UPDATE block_content_revision__body SET body_format='full_html' WHERE body_format='full_html1';
UPDATE comment__comment_body SET comment_body_format='full_html' WHERE comment_body_format='full_html1';
UPDATE node_revision__body SET body_format='full_html' WHERE body_format='full_html1';

I use these queries in addition to the full_html1 queries I use to fix the Drupal 6 “Photo” content type problem.

Fix all “langcode” problems

I also run all of the following queries to fix the “langcode” problems created by the Drupal 6 to Drupal 8 migration:

UPDATE block_content SET langcode='en';
UPDATE block_content__body SET langcode='en';
UPDATE block_content_field_data SET langcode='en';
UPDATE block_content_field_revision SET langcode='en';
UPDATE block_content_revision SET langcode='en';
UPDATE block_content_revision__body SET langcode='en';
UPDATE file_managed SET langcode='en';
UPDATE menu_link_content SET langcode='en';
UPDATE menu_link_content_data SET langcode='en';
UPDATE node SET langcode='en';
UPDATE node__ad_groups SET langcode='en';
UPDATE node__body SET langcode='en';
UPDATE node__category SET langcode='en';
UPDATE node__field_bookmark_url SET langcode='en';
UPDATE node__field_image SET langcode='en';
UPDATE node__field_photo SET langcode='en';
UPDATE node__field_photo_d8 SET langcode='en';
UPDATE node__field_quote_author SET langcode='en';
UPDATE node__field_quote_url SET langcode='en';
UPDATE node__field_source_url SET langcode='en';
UPDATE node__field_tags SET langcode='en';
UPDATE node__field_text_author SET langcode='en';
UPDATE node__tags1 SET langcode='en';
UPDATE node__upload SET langcode='en';
UPDATE node_access SET langcode='en';
UPDATE node_field_data SET langcode='en';
UPDATE node_field_revision SET langcode='en';
UPDATE node_revision SET langcode='en';
UPDATE node_revision__ad_groups SET langcode='en';
UPDATE node_revision__body SET langcode='en';
UPDATE node_revision__category SET langcode='en';
UPDATE node_revision__field_bookmark_url SET langcode='en';
UPDATE node_revision__field_image SET langcode='en';
UPDATE node_revision__field_photo SET langcode='en';
UPDATE node_revision__field_photo_d8 SET langcode='en';
UPDATE node_revision__field_quote_author SET langcode='en';
UPDATE node_revision__field_quote_url SET langcode='en';
UPDATE node_revision__field_source_url SET langcode='en';
UPDATE node_revision__field_tags SET langcode='en';
UPDATE node_revision__field_text_author SET langcode='en';
UPDATE node_revision__tags1 SET langcode='en';
UPDATE node_revision__upload SET langcode='en';
UPDATE search_dataset SET langcode='en';
UPDATE search_index SET langcode='en';
UPDATE shortcut SET langcode='en';
UPDATE shortcut_field_data SET langcode='en';
UPDATE taxonomy_term_data SET langcode='en';
UPDATE taxonomy_term_field_data SET langcode='en';
UPDATE url_alias SET langcode='en';
UPDATE user__roles SET langcode='en';
UPDATE user__user_picture SET langcode='en';
UPDATE users SET langcode='en';
UPDATE users_field_data SET langcode='en';

I skip all of the “comment” tables, because (a) I don’t know what those fields look like, and (b) at the moment I don’t care about them.

In retrospect it may be better to add a WHERE langcode='und' to the end of those queries, and I’ll probably try that in my next set of tests. (FWIW, everything on my sites is in English, so these queries should not do any harm, and I have seen issues where a langcode of und has caused problems. I think that was in regards to the Photo content type.)

More to learn ...

I still have much more to learn about this process, but I have gotten the migration to the point where I can see all of my old blog posts, and the old URL aliases seem to be working as well.

I’ve also started theming the D8 website. Drupal 8 themes are a significant change from Drupal 6 themes, but I cracked that code in about 1.5 days of work, so now all I have to do is get the theme looking as desired. (I don’t have to worry about the nuts and bolts any more, just implement the desired style.)

I’ll share more here as I learn it, including a few images, but for today, that’s what I know.