Configuration Management and Features: a look at Drupal 8
What CMI will bring to D8 and "Poorman's Features" for packaging configuration in D8
An update to this post is now available at http://nuvole.org/blog/2014/jul/15/packaging-and-reusing-configuration-d....
We have always told attendees of our Drupal 7 "Code-driven development" trainings that embracing the idea that configuration must be stored in files and not in the database would make their Drupal development future-ready: the specific processes would necessarily change but the concept would stay and be reinforced in Drupal 8, thanks to the nice work being done in the Configuration Management Initiative.
And this was right. The progress done in CMI is very good, to the point that in our coming DrupalCon training in Prague, Code-Driven Development: an Effective Drupal Workflow, from D7 to D8 we will explore in detail how things work in Drupal 7, but for each topic we'll also describe what is going to improve/change in Drupal 8.
Configuration Management in a nutshell
From a site builder's point of view, Configuration Management in Drupal 8 is visible as two items in admin/config/development
: "Configuration Export" and "Configuration Import".
The Export functionality has no further options, and it provides you with a config.tar.gz
file containing hundreds (180+ on a clean installation, many more on a feature-rich test site) of files in YAML format, human- and machine-readable. All the site configuration is there: node types, their fields, permissions, Views, theme settings, variables...
The Import functionality, on the converse, will import a config.tar.gz
file, show you any configuration changes between the currently active configuration and the one you are trying to import and allow you to replace the current configuration with the one in the provided files.
For many developers, this is a dream come true: with D8, Drupal Core will support a file-based configuration, allowing developers to track changes, put configuration under version control, update a production site cleanly... basically, all the advantages that we have described as selling points for the Features module in the last several years.
The Future of Features
So, if the major selling points of the Features module are now in core, does Features have a future in Drupal 8?
It still does, but it needs to be repurposed. So far, it had a dual functionality, serving as:
-
A machinery to export/import configuration from database to code. This will no longer be necessary in Drupal 8. Configuration lives in files and the database is used only for caching. For the same reason, an important problem in Drupal 7 development ("How do I make configuration exportable when there is no native support for Features?") is now solved for good.
-
A convenient way to package and reuse configuration across multiple sites. This is extremely useful to developers and not completely covered by Configuration Management in Drupal 8, even though the basic components are there.
Poorman's Features: emulating Features in Drupal 8
Let's see how it is possible to package configuration and emulate, manually, what Features and Drupal 7 allow today.
As an example use case, we will package a "Blog Feature".
1: Create and export configuration
Create the Blog content type, configure its fields (use proper naming for fields: field_blog_image
and so on) and a classic view with a block and page display. Then go to admin/config/development
and export your configuration into the config.tar.gz
file.
2: Package relevant configuration into a module
Create a simple feature_blog
module containing:
feature_blog.info.yml
: a basic.info
file in the Drupal 8 format.
name: Blog<br>type: module<br>description: 'A Blog content type and related configuration.'<br>package: Features<br>version: 8.x-0.1<br>core: 8.x
feature_blog.module
: an empty module file, needed for correct Drupal operations.
<?php<br> // Drupal needs this empty file.
- a
config
subdirectory: copy to this folder all relevant files fromconfig.tar.gz
; filenames are quite helpful here, as it will be enough to copy all files that have "blog" in their name.
.<br>|-- config<br>| |-- entity.display.comment.comment_node_blog.default.yml<br>| |-- entity.display.node.blog.default.yml<br>| |-- entity.display.node.blog.teaser.yml<br>| |-- entity.form_display.comment.comment_node_blog.default.yml<br>| |-- entity.form_display.node.blog.default.yml<br>| |-- field.field.field_blog_image.yml<br>| |-- field.instance.comment.comment_node_blog.comment_body.yml<br>| |-- field.instance.node.blog.body.yml<br>| |-- field.instance.node.blog.field_blog_image.yml<br>| |-- node.type.blog.yml<br>| `-- views.view.blog.yml<br>|-- feature_blog.info.yml<br>`-- feature_blog.module
3: Make the exported files portable (remove UUIDs)
The feature is ready, but it will only work if imported in the same Drupal 8 site. We need to make it portable to other sites.
The main problem here is that Drupal assigns UUIDs (Universally Unique Identifiers) to each component. When you add, say, an "image" field to a content type, you create an instance of the "image" field, and to describe this relationship Drupal will rely on the UUID of the "image" field. Since UUIDs are site-specific, trying to import this configuration on another site would result in an error message like:
Drupal\field\FieldException: Attempt to create an instance of<br>unknown field 84e904df-2f14-46e8-9700-e00c5ca3f7d3<br>in Drupal\field\Entity\FieldInstance->__construct()<br>(line 252 of .../core/modules/field/lib/Drupal/field/Entity/FieldInstance.php).
Fortunately, in this case configuration import is designed to accept either names or UUIDs for describing the field this is an instance of. So it is enough to edit all files containing field.instance
in their name and manually replace UUIDs with machine names (or just add machine names), something like the following:
-field_uuid: 84e904df-2f14-46e8-9700-e00c5ca3f7d3<br>+field_name: field_blog_image
Note that this relies on the specific handling of the FieldInstance class and may not be a general solution.
Edit: also note (see comments) that it is important to include a hardcoded UUID if you want to avoid that your configuration items are seen by Drupal as different items between your development and production sites, causing configuration import/export between the two to fail.
4: Import the feature on another site
Our module/feature is now ready to be imported. Just copy it to the /modules
folder on another site, or a subfolder of it (this is now the recommended location to add modules) and enable it.
Your content type and configuration will be immediately available.
Possible improvements
The Configuration Management in Drupal 8 will bring to Drupal Core a clean, unified, professional way to deal with configuration. There will still be the need for a module like Features for packaging and reusing configuration.
Some implementation details of Configuration Management do not behave well in this respect: for example, UUIDs are problematic and user permissions are stored in a packaging-unfriendly way (one file per each user role, with roles identified by UUID).
But, overall, the future looks bright and code-driven! And, as we have seen, it is already entirely possible to manually create basic "Features" (i.e., modules with configuration) that will work in Drupal 8.
Tags: Drupal PlanetDrupalConTrainingCode Driven Development