Migrating from Drupal 7 to Drupal 8: my experience, the many obstacles, and their solutions

Submitted by Dan on Tue, 02/26/2019 - 08:51

You can't really call yourself a Drupal developer if your personal site is still on Drupal 7. Right? So it was high time for me to upgrade Dannix from D7 to D8. Here's how I did it, the problems I ran into, and what I did to overcome them. 

  1. First, I started with a fresh install of Drupal 8 on my server.
    • I started with unzipping a tarball of the latest D8 release in the a directory ~/public_html/drupal8/, I setup up a new subdomain and pointed it at that directory, then I set up a new database and db user.
    • When I went to run the install script, I received this error printed to an otherwise blank white screen:
      • Your PHP installation is too old. Drupal 8 requires at least PHP 5.6.0
    • Thankfully this was pretty easy to overcome as  my provider, HostGator, allowed me to select a version of PHP by configuring a custom php.ini file (note that this can also be accomplished via the cPanel, but I like doing things the hard way I guess). I was still using PHP 5.4, the default choice, so I simply changed it to PHP 5.6. Afterwords, I made sure that all of my Drupal 7 sites were still functioning and I sent out emails to my users to let them know. I know that a few modules, like reCAPTCHA, require at least PHP 5.5 so now I can finally install those updates for my remaining D7 sites.
    • Now I could run the install script. I got though the initial steps (selecting the language, time zone, ect) but when it got to the the system requirements step, I got this error:
      • PHP
        5.6.30
        Drupal will drop support for this version on March 6, 2019. Upgrade to PHP version 7.1 or higher to ensure your site can receive updates and remain secure. See PHP's version support documentation and the Drupal 8 PHP requirements handbook page for more information.
    • Well that's frustrating. After a little reading, I learned that PHP 5.6 had reached EOL (end of life) only a few weeks ago, and therefore was no longer receiving security support. But upgrading PHP from 5.6 to 7.1 seems like a pretty big jump and would surely cause several D7 modules to break. In reality it's not that big of a leap because there's no PHP 6 and PHP 7 is largely backwards compatible with code written for PHP 5, and by now Drupal core and any contrib module with a moderate user base has been updated if necessary.
    • So I'll need to upgrade my D7 sites to use PHP 7 in the near future, but for now I decided to focus on upgrading only Dannix to D8. I could set the PHP version to 7.1 for only my new directory ~/public_html/drupal8/ by making another php.ini file and adding it to that directory. 
    • The rest of the install went perfectly smooth.
  2. Next, I started migrating the content over.
    • First thing I did was enable the Migrate modules
    • I wanted to use Drush for the migration, but apparently HostGator does not allow Drush as I'm only given access to jailshell instead of bash. Even after using Symphony to successfully install Drush, when I tried the drush --version command, I got -jailshell: drush: command not found
    • So I simply used the UI version of the migrate process. I followed all the instructions and it was pretty easy. 
    • It said that 32 modules would not get updated and 38 would, many of which would become core modules in D8.
    • First attempt:
      • After migrating the content over, first thing I noticed was that the old Views had not been imported. I expected this however, as I was warned would be the case.
      • Looking at the content itself, the text bodies were not displaying. However, when editing the node the content was in the text editor! So the text was in the database, but was not displaying...
      • The reason? On the D7 site, I was using a text filter called GeSHi Filter, which provides syntax highlighting for code block. But because it wasn't installed on my D8 version, that filter didn't exist so instead it was using filter_null, which returns an empty string. 
      • I could have tried to install GeSHi onto the D8 module, but I thought it would be clearner if I started over again with a fresh install of D8 (drop all the database tables and delete anything in sites/default/files/)
    • Second attempt:
      • First, I disabled the GeSHi filter on my D7 sites
      • Then I migrated the content just as before
      • Now the content text was displaying just as it should, but there was no images! 
      • The reason? How I entered the public files field in the migrate config. I was confused about the public files path. 
        • wrong: /home1/dannix/public_html/drupal7/sites/default/files
        • correct: /home1/dannix/public/_html/drupal7
      • Delete the d8 install and start over again. Yes I could have copied the files with a simple linux command, but I wanted to do it the right way.
    • Third attempt:
      • Finally, the content was all migrated over correctly. 
      • Only one problem: all the old images that were generated for the image styles weren't getting created, and didn't get copied over during the migration. 
      • I was tired of doing things the hard way so I did this:
        • cp -R ~/public_html/drupal7/sites/default/files/styles/* ~/public_html/drupal8/sites/default/files/styles
  3. With the content all moved over, I needed to recreate the Views.
    • In D7, I was using an advanced contextual filter to display content based on a taxonomy term found in the URL. This allowed me to dynamically create any number of views for a taxonomy. 
    • But in D8, the contextual filter I needed, "has taxonomy term ID", didn't have the option to convert the ID to the term Name as it did in D7. Therefore the term ID needed to be in the URL and instead of the term name. My workaround solution was to create URL aliases for all the term names and IDs for the view. 
    • I also wanted to make the taxonomy term filter (the basic version, not the contextual one) exposed to a user to select. Easy enough right? It's built right in, just like in D7. But I didn't like how, for just one exposed filter, was shown in a drop down select field, so I wanted to hide it. In hindsight, I'm not sure why I chose JavaScript to hide it instead of CSS, but I wanted to put a little jQuery in some unfiltered footer text. That's when I ran into another problem, as discussed in step 4 below.
  4. The PHP filter.
    • I wanted to insert some JavaScript in a view's footer text. Simply putting it between <script> tags wasn't working, not to my surprise, so I needed to use the PHP filter. 
    • In Drupal 8, the PHP filter is a contrib module as opposed to being in core like in D7, so I installed the module but received this error when trying to enable it:
      • unable to install PHP Filter, filter.format.php code already exists in active configuration.
    • To get it enabled, I first had to do this:
    • Maybe if I had dissabled the PHP filter in the D7 site before the migration I wouldn't have had this problem
  5. Webforms
    • I only had one webform to worry about: contact me. 
    • The Webforms module wouldn't update with Migrate. Needed to install d8 version manually.
    • When trying to enable the Webform Node module:
      • "Webform content type already exists, please delete the Webform content type before installing the Webform node module."
    • so I set off to delete the Webform content type, when I encountered this:
      • "Webform is used by 1 piece of content on your site. You can not remove this content type until you have removed all of the Webform content."
    • Deleted the /conact page
    • Webform Node installed
    • added new webform, /contact
  6. Taking the D7 site live
    • I should first note that I was using this .htaccess config to use my primary domain in a subdirectory, ~/public_html/drupal7, which undoubtedly made this process a little more challenging
    • So to direct the dannix.net URL from the D7 site to the D8 site, I simply changed the directories in the .htaccess config:
      • old: RewriteRule ^(.*)$ drupal7/$1
      • new: RewriteRule ^(.*)$ drupal8/$1
    • It worked, but when trying to log into the CMS I got this error:
      • Redirects to external URLs are not allowed by default, use \Drupal\Core\Routing\TrustedRedirectResponse for it.
    • I first tried setting the $settings['trusted_host_patterns'] in default/settings.php - didn't work.
    • The solution was to follow the steps in this comment
      1. In public_html/.htaccess add the following content
        RewriteRule ^$ drupal8/$1 [L]
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteRule ^(.*)$ drupal8/$1 [L]

      2. In public_html/drupal8/.htaccess:
        # Modify the RewriteBase if you are using Drupal in a subdirectory or in a
        # VirtualDocumentRoot and the rewrite rules are not working properly.
        # For example if your site is at http://example.com/drupal uncomment and
        # modify the following line:
        RewriteBase /drupal8

      3. in ~/public_html/drupal8/sites/default/settings.php add this code at the bottom

        if (isset($GLOBALS['request']) and
        '/subdirectory/index.php' === $GLOBALS['request']->server->get('SCRIPT_NAME')) {
            $GLOBALS['request']->server->set('SCRIPT_NAME', '/index.php');
        }

    • With that in place, I was able to log in. But when I was logged in, the admin style sheet was not getting downloaded
      • getting these errors: Refused to apply style from '<URL>' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.
      • but the main stylesheets for the site were working fine, maybe because it was Bootstrap and was getting loaded from a CDN
    • I noticed that several files where being served strangely. Their URL was like: dannix.net/sites/default/files/logo.png?q=sites/default/files/logo.png
    • Which was a pretty strong indication that my public_html/.htaccess file was not set up correctly.
      • I had the line: RewriteRule .* drupal8/index.php?q=$0 [QSA]
      • I just needed to remove that one and the associated lines above it (commented them out).
    • And suddenly everything worked as it should!
    • Proof that .htaccess is black magic.
  7. I'm now writing my first article on the new Drupal 8 site, therefore it's a success! There's still a lot of work for me to do, like setting up Google Analytics and IMCE, working on the new theme (Bootstrap), etc. But hopefully this experience I'm sharing will be helpful to anyone out there running into these problems.