Skip to content

Instantly share code, notes, and snippets.

@MaffooBristol
Last active September 15, 2018 10:10
Show Gist options
  • Save MaffooBristol/843903caabf8505e5c7f64a43b0df620 to your computer and use it in GitHub Desktop.
Save MaffooBristol/843903caabf8505e5c7f64a43b0df620 to your computer and use it in GitHub Desktop.
Halo features documentation (WIP)

Features

By Maff 14/09/2018

Features is a method of synchronising Drupal site settings and structure (eg, content types, views, etc) between different instances, such as the live site, dev site and your local copies.

By generating a feature, you select a portion of the site's settings that exist in the database and copy them to code. This is similar to if you were to programatically generate a content type and put it into a module. The features module will take an existing content type generated through the front-end GUI and replicate it using code. This is also similar to what would happen if you choose "export" from views, as well as many other modules that have similar functionality to this. However, this doesn't apply to generated content such as nodes, users, taxonomy terms, menu links, etc. Certain contrib modules can allow you to do this, for example if your content has a UUID (which means it can be versioned), but it tends to be an anti-pattern. Normally this stuff would be generated manually, or by doing a feeds import.

In Drupal 7, this is done exactly as above, by creating code that, when imported into another site, will synchronise and save into the database. This means that the setup of a site can be put into version control and pushed upstream without having to copy databases over the top of another, or create content multiple times. The major benefit of this is that certain stuff that is specific to a site (for example, having caching on a live site but not on a dev site) can be kept independent of that which is always the same across environments, such as content types.

In Drupal 8, the theory is very similar but the method is a bit different. Features 8.x utilises the existing config system and componentises it. Config was developed as a core version of features, but it's lacking in many ways, such as being able to specify a different feature for a different... well, feature.

In Drupal 8, features can be managed in /admin/config/development/features. When you generate a feature, you specify the different components that define that functionality. For example, you may have a blog feature that contains the blog content type, the fields that exist on that blog type, the view that lists the blog posts, the permissions for who can create blog nodes, the display modes for that blog, etc. This is generally regarded as the right way of doing it, but some people will create a feature for all content types, another for all views, etc. This is wrong and those people are morons. Basically, a feature should exist on its own, have little to no dependencies, and be able to be switched on and off at will without affecting other aspects of the site.

A general thing to remember too is that field storage and field instances are different things and need to be treated differently in features. The field storage, or definitions, can be used across multiple places in your site, and therefore can't really be attached to a specific feature without causing issues. An example of this may be where your blog content type has a "hero image" field, but so does your standard page. For this, it makes sense to put this definition into a more generic feature that is always required (often this will be a feature called "core"). Field instances however, are attached to the entity directly and can be safely included in the more specific feature.

Feature updating

This can be done two ways:

GUI

This is done the same way as generating a feature for the first time, however it will act as an update rather than a create. For example, if you go to the URL /admin/config/development/features/edit/ur_feature_name

Hitting "save" will update the local code with the current state of the database. Hitting "download archive" will give you a zip file than can be saved and used to overwrite the existing code. The latter is useful when you're exporting a feature from a live site, but can't update the local code (it's not in Git, for example).

Drush

Running drush fu ur_feature_name -y will update the code with your local database state. I'd highly recommend doing a git diff before committing anything in and making sure that it looks okay, because it's easy to export stuff you don't want to export. You can also run drush fua -y to update all features, but this often doesn't work because features is a bit shit sometimes. It's better in Drupal 7, I've found, than it is in 8. Sometimes you just need to do things a bit manually.

Feature importing/reverting

GUI

In the features list, you may see a link on the right that says "changed" or "new detected". I don't really understand what the difference is... I think that if you create a new content type or something and it doesn't exist yet in the site where you're trying to import, it will say "new detected". Clicking either of these links will take you to a page that shows the differences between the state of the code and the state of the database, and you can select all or just specific bits of the feature to import. On the feature edit page, you may also get an import button if "new detected" is true. Features can be dodgy, and often will say stuff is still available to update or import, even if it's just been done, so take it with a pinch of salt.

Drush

Running drush fr ur_feature_name -y or drush fi ur_feature_name -y will revert or import respectively. Be careful when running these commands, because if you (say) create a content type locally, then want to export it and accidentally revert/import, you can undo your work. So regular commits, regular backups, and all that jazz is highly recommended. As above, fra and fia can revert/import all, but as above it can be a bit shit.

Feature components

GUI

There isn't really one... closest is probably admin/config/development/features/diff

Drush

Running drush fc will give a list of the different types of components that can be exported, typing the name and hitting enter (eg, view) will show all those components of that type (so, all views) and what feature they are in (D7) or in and could be in (D8). When I say 'could be in', I mean, hitting save in the feature will export that component, but it doesn't mean it's actually represented in code. This is in a way a bug, but it's something to be aware of.

Moving components between features

Again, I wish there was an easy way of doing this, but you will actually have to just remove the component definition from one feature and then export another feature with it in. If you have "allow conflicts" selected, it will make it so you can export the component into multiple features, but this is highly recommended against because it can cause some serious issues (imagine if one feature contains one version of a component, and another feature contains a different version of the same component. Just imagine!!!)

Where to put them

Generally I put features into modules/features (or sites/all/modules/features), but some people put them into modules/custom. Matter of choice. Equally I normally name them Project feature: Ur feature name: project_feature_ur_feature_name.

Anything else?

I'll update this document as I go along, if I think of anything...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment