Writing Drupal 7 code to be upgradable to Drupal 8

Drupal

Drupal has always traditionally supported two versions, the current version the previous version. This means that currently Drupal 8 (current), and Drupal 7 (previous), are supported. Though Drupal 8 is newer, Drupal 7 is still often the preferable version for various reasons. At Digital Garden, we have been using Drupal 8 for two years now, so we are able to use D8 knowledge to write D7 code in a manner that allows it to be more easily upgraded to D8.

Before going into the specifics of how to write D7 code in a forward-compatible manner, it’s important to first understand what Drupal is at its core. Drupal core is a framework; it provides a number of tools to work with, and a core onto which new functionality can be attached, much like a ball of velcro that can have items attached, or a piece of lego that can have items snapped on. The CMS that most Drupal users are familiar with is built on top of this framework, using the given tools that core provides. Coders however interact with Drupal on the framework level, using said tools to create new functionality that isn’t part of the core framework, or the CMS that lies on top of it.

Now that we’ve looked at what the core of Drupal is, we can discuss the three ways we at Digital Garden write Drupal 7 code, to make it as easy as possible to upgrade to Drupal 8. The three ways are:

  1. Have an understanding of how Drupal 8 APIs have evolved since Drupal 7

  2. Keep custom logic in external files, using small bits of code to attach the functionality to Drupal

  3. Write Drupal 7 code using Drupal 8 standard PSR-4 compliant PHP

Have an understanding of how Drupal 8 APIs have evolved since Drupal 7

In the intro, I mentioned that Drupal core provides a number of ‘tools’ to help developers attach functionality onto core. Programmers call these tools ‘APIs’, and Drupal provides a number of them. Some of them, such as the Database API (for retrieving data from the database) are relatively unchanged, and can be used in D8 nearly as-is. Other APIs, such as the Form API (for building custom forms) have changed, so when we use these APIs, we want to write them in as D8-friendly a manner as possible.

In D7, a custom form was created by adding three functions into a .module file to define the form, add validation, and handle submission. A .module file was the default file type into which code was placed in D7. To define a form, the .module file would have these functions (as an example):

user_login_form()

user_login_form_validate()

user_login_form_submit()

In D8 however, each form is defined in its own file (called a class), with three functions that define, validate and handle submission of the form. These three functions are always named the same in every class that defines a form:

buildForm()

validateForm()

submitForm()

To write D8-friendly D7 code, we use a combination of these two methods. First, we write our external file (class), using the three D8 function names listed above. Then in the D7 .module file, we include the three D7 functions. Inside the D7 functions, we run the D8-style functions.

This allows us to have a file that will remain nearly unchanged in D8, while still using D7 methodology.

When we upgrade to D8, we simply remove the D7 functions from the .module file (as they are unnecessary), and make a few changes to the metadata of our external file (class), allowing it usable by D8, with little change to the actual code.

Keep custom logic in external files, using small bits of code to attach the functionality to Drupal

Another way of writing forward-compatible Drupal 7 code, is to decouple custom logic from Drupal altogether, and use small bits of code to ‘attach’ the custom logic (code) to Drupal core. For example, imagine a module that pulls a file from a remote server, reads through the data, and emails the data to an administrator.

In this situation, most of the code is not Drupal specific. The Drupal-specific part is to create a page or a background process where this functionality can be run. To make our code more easily portable to D8, the logic is kept in an external file (class), and small bits of code are added to Drupal that in turn ‘use’ this external code. When we upgrade to Drupal 8, we only need to update the Drupal-specific code, while the code that provides our functionality can mostly remain unchanged. In D7, we traditionally would have included all functionality in the same file, requiring more effort to separate it out when upgrading to D8.

Write Drupal 7 code using Drupal 8 standard PSR-4 compliant PHP

One of the major differences between Drupal 7 and Drupal 8 is that the code paradigm changed. While both versions are built on the PHP programming language, Drupal 7 uses ‘procedural’ code (https://en.wikipedia.org/wiki/Procedural_programming) and Drupal 8 uses ‘object oriented’ code (https://en.wikipedia.org/wiki/Object-oriented_programming). The differences between these are beyond the scope of this document, however it’s important to understand that a fundamental difference exists. For ease of upgrade between D7 and D8, we write code using PSR-4 Object-Oriented code, ensuring an easy upgrade to Drupal 8. To be able to use Object-Oriented PHP, we include a single module into D7, XAutoload (http://dgo.to/xautoload). This module allows us to use PSR-4 compliant D8 style code, in the D7 framework.

So to review, to write D7 code in a D8-friendly manner, we follow a 3-step approach. First, we use our knowledge of the differences between D7 and D8 APIs, to write code that will require the least changes when updating. Second, we bundle non-Drupal code in external files, and finally we include the XAutoload module, writing our external code in a D8 friendly format.