Welcome to the 6th installment of an 8-part blog series we're calling "The Ultimate Guide to Drupal 8." Whether you're a site builder, module or theme developer, or simply an end-user of a Drupal website, Drupal 8 has tons in store for you! This blog series will attempt to enumerate the major changes in Drupal 8.
Please note that since Drupal 8 is still under active development, some of the details below may change prior to its release. Still, since Drupal 8 is now feature-frozen, hopefully most info should remain relevant. Where applicable, Drupal 7 contrib equivalents of Drupal 8 features will be noted.
New configuration management system
Probably the most looked-forward-to change in Drupal 8, for both developers and site builders, is the new configuration management system in Drupal 8. In Drupal 7 and below, both content and configuration were saved to the database (sometimes with a mix of both in the same table!), making deploying configuration changes from one environment to another (e.g. dev to prod) a very tricky affair. A variety of workarounds emerged for this, including hook_update_N(), Features module, and of course the old standby: carefully writing the configuration changes you made on dev down on a napkin and then manually repeating them in production. ;) However, all of these were attempting to circumvent the fundamental problem that Drupal core didn't properly support configuration deployment natively… until Drupal 8, that is!
In Drupal 8, all configuration changes (both standard admin settings forms such as site name, as well as any ConfigEntity including Views, user roles, and content types) run through a unified configuration API. Each environment has both an "active" store (where configuration settings are written to and read from on every page load) as well as a "staging" store to hold configuration changes from other environments that are about to be imported, for review. For performance, by default the active store is in a "config" table in the database (somewhat analogous to the "variables" table in D7 and below), though the storage location is swappable. Configuration Development module, for example, writes active configuration out to YAML files in the file system, just as core does with the staging store.
Drupal 8 also ships with a basic UI to do both single and full configuration imports and exports, and configuration can also be moved around via the command line with Drush's
config-* commands, which is handy when using version control systems such as Git.
The basic workflow (after making whatever configuration changes to your Drupal 8 site) is:
- On the dev site, export your site's "active" configuration. You'll receive a tarball that consists of lots of YAML files.
- On production, import the files, which places them into the config "staging" area.
- In the configuration UI, you can now see a list of what configuration settings have changed, and have an opportunity to view a "diff" of changes in advance.
- If changes are acceptable, you can choose to synchronize them, which will replace production's current active store with the contents of staging, and become the new values that Drupal will use to build pages.
Of course, there are some settings that are specific to a given environment and you don't want to be deployed across environments. One such example is a timestamp storing the last time cron ran. For these, there's a "sister" API to the config API called the State API for these more ephemeral settings.
What about content deployment?
While Drupal 8 core doesn't ship with support for migrating content such as nodes, users, and taxonomy terms between sites (though this could happen in a later feature release such as 8.1.0 or 8.2.0), one welcome addition to Drupal 8 has been the introduction of UUIDs (Universally unique identifiers) to every piece of content, such as b2423870-b19b-45e7-8407-076aee906870. These UUIDs can be used to determine whether a piece of content exists on a given destination site, regardless of whether the content's numeric ID conflicts, making content imports/exports infinitely easier. Keep your eyes on the Deploy module for a Drupal 8 version. If you're still on Drupal 7, you can get similar functionality to what core offers via the Universally Unique IDentifier module.
Entities, entities, everywhere!
Entities were a key new feature and concept in Drupal 7, abstracting the ability to add fields to other types of content than just nodes, such as users and taxonomy terms. However, the Drupal 7 core API was severely limited, and required use of modules like the Entity API module to further flesh out basic functionality, such as saving and deleting.
In Drupal 8, the Entity API has been completely re-hauled to not only fill the gaps in functionality from Drupal 7, but also to greatly improve developer experience. All entities are now classed objects that implement a standard EntityInterface (no more guessing which of the 100 entity hooks you're required to implement!), with baked-in knowledge about the active language. Compare and contrast:
<span style="color: #000000"><span style="color: #0000BB"><?php<br /></span><span style="color: #FF8000"># Drupal 7 code.<br /></span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">title<br />$node</span><span style="color: #007700">-></span><span style="color: #0000BB">body</span><span style="color: #007700">[</span><span style="color: #0000BB">$langcode</span><span style="color: #007700">][</span><span style="color: #0000BB">0</span><span style="color: #007700">][</span><span style="color: #DD0000">'value'</span><span style="color: #007700">]<br /><br /></span><span style="color: #FF8000"># Drupal 8 code.<br /></span><span style="color: #0000BB">$node</span><span style="color: #007700">-></span><span style="color: #0000BB">get</span><span style="color: #007700">(</span><span style="color: #DD0000">'title'</span><span style="color: #007700">)-></span><span style="color: #0000BB">value<br />$node</span><span style="color: #007700">-></span><span style="color: #0000BB">get</span><span style="color: #007700">(</span><span style="color: #DD0000">'body'</span><span style="color: #007700">)-></span><span style="color: #0000BB">value<br />?></span></span>
Nearly anything you can create more than one of has been converted to an entity, bringing much greater consistency to Drupal development overall. There are two kinds: Config entities and Content entities. What's the difference?
Content entities also sport some nifty new features compared to Drupal 7, such as revisions on not just nodes but also custom blocks, and the ability to add comments to any content entity (so you can even have comments on comments—WOAH). The Site Builder Improvements article has more information about other entity-related features.
What does this mean for you as a developer? It means that between the Entity API and the Config/State API, there is almost never a reason to create and manage your own database tables by hand in Drupal 8. By using these standard APIs, you will both benefit from writing less brittle code, and also benefit from portability to other databases such as MongoDB.
A major focus for Drupal 8, both to enable the creation of Drupal-backed mobile applications, but also to facilitate cross-site communication and better integration with third-party resources, is a native REST API built into Drupal 8 itself provided by the RESTful web services suite of modules. This allows for fine-grained configuration of which resources should be available (nodes, taxonomy, users, etc.), what HTTP methods are allowed against those resources (e.g. GET, POST, PATCH, DELETE…), and which formats and authentication are used to access those resources. See the contributed REST UI module which provides an interface for this configuration. Then, for each allowed HTTP method you can also set permissions on which role(s) on your site may access the resources via that method. This allows anonymous users to GET but only administrators to POST, for example.
Once the various RESTful Web Services modules are configured properly, you can get a big clump of machine-readable data representing your site content, such as this:
...<br /> [title] => Array<br /> (<br />  => Array<br /> (<br /> [value] => Hello, world!<br /> [lang] => en<br /> )<br /><br /> )<br />...<br /> [body] => Array<br /> (<br />  => Array<br /> (<br /> [value] => <p>This is my <strong>awesome</strong> article.</p><br /> [format] => basic_html<br /> [summary] =><br /> )<br /><br /> )<br />...
What good is that? Plenty! Here's one example of retrieving information from Drupal 8 in JSON and displaying it in a standalone jQuery Mobile app:
And one final web services feature in Drupal 8 offered by the RESTFul web services module is the ability to add a "REST export" display to any view:
This means you can easily create JSON or XML feeds of custom dynamic content from your Drupal site, just by clicking them together!
And on a final happy note, caching in Drupal 8 has been improved across the board.
- Entity cache module is now in core
- Cache tags allow for much more granular cache clearing when content or settings are updated on the site.
- All caching features such as CSS/JS aggregation are turned on out of the box, making Drupal 8 fast by default.
While we're still working hard on improving D8's performance overall, this extra caching should help most page loads come up lickety-split.
Whew! That's a wrap!
This article offered a taste of some of the under-the-hood code changes coming to Drupal 8. Join us next time, when we'll talk more in-depth look at major API changes in Drupal 8 and what they mean for you!