Features + Drush = Drupal Goodness

A basic Drush and Features workflow

I've used both Features and Drush for a few years but until recently didn't know you can create, update and manage your features all with Drush. I can thank the good folks on a new dev team I'm working with who pointed me in the right direction for this method and I ran with it from there; I thought I'd share my early experience with these methods.

Time Saver

If you've got a legacy Drupal 6 site to manage, creating and managing Features with Drush is good news as Features UI in D6 can sometimes be unwieldy and almost unusable.

Whether it's Drupal 6 or 7, this method is a huge timesaver and you'll work much smarter and faster as a developer, in this case Drush plus Features.

Getting Started

It's pretty easy to get up and running once you get the hang of the syntax and terminology. Of course you'll need Drush, Features and Chaos tool suite (ctools) installed on your site along with any other contrib modules from which your Feature will be created such as Views.

Approaching Feature creation with Drush is similar to the UI method in the sense that you'll be adding components to the Feature but I'll also show you a few shortcuts along the way. To start, as an example I want to incorporate a View into my Feature so I'll invoke a basic Drush command in Terminal:

drush fe --d events_feature views:latest_events

The above string says to create a new feature, fe, short for features-export, using debug (--d), and then name it "events_feature" and use a view called latest_events. We use the debug function as it provides useful information if something goes wrong and as you'll see later will exclude any bad code along the way.

After this command, you should see a return message in Terminal:

Will create a new module in sites/all/modules/features/events_feature
Do you really want to continue? (y/n):

After confirming above, you'll now have a new folder that contains the Feature. I found that in my tests with Drupal 6, the default location is sites/all/modules whereas in Drupal 7, the default location is sites/all/modules/features/. Of course Drush has a means of specifying the location of your Feature by invoking the --destination command. It would look something like this:

drush fe --d --destination="sites/all/modules/custom"  events_feature views:latest_events

Here we tell Drush to put the new feature in a modules custom folder.

Adding and Updating

Until now, we've only covered creating a new Feature with Drush but what about updating and adding components? Well, there's plenty more we can do and here is where the fun starts. The first thing you'll want to do is drush cc all and then enable the feature so we can work with it -- drush en events_feature -- this is just like enabling a regular module. If we look in the new .info file that was created, we see some basic info:

name = events_feature
core = 7.x
package = Features
dependencies[] = views
features[ctools][] = views:views_default:3.0
features[features_api][] = api:2
features[views_view][] = latest_events

This all looks familiar but note that dependancies and other info was added automatically when Drush created this. The package indicates a grouping similar to module grouping only this would apply to the the Features UI main page. I usually add some useful additional info as well including a description, version number and module path.

description = Latest Events Feature
version = 7.x-1.0
project path = sites/all/modules/custom

I've Got the Power...

Let's say you create an image style called "adaptive" and you've updated your view to use that style. First we'd simply add this new component to the Feature's info file. The best way to determine what components are available on your site is to have Drush compile a components list:

drush fc

You'll now get a nicely printed list in Terminal of available components. Choose an item from the list and you'll be presented with all sub-items within the component, where they are being used and which ones are free to use. I'd then choose image and see:

Available sources                              
 image:50x50_avatar  Provided by: user_follow
 image:35x35         Provided by: user_groups
 image:50x50         Provided by: user_groups

From the list, I can now formulate my component syntax for the adaptive image stye ready to be put into the .info file.

features[image][] = adaptive

Now we'll update the Feature via Drush usingdrush fu, short for drush features-update.

drush --d fu events_feature

This is where the power of Drush and Features comes into its own. By simply adding a new component to the Feature's info file and updating via Drush, it now will find and add dependencies, variables, ctools instances and anything related to Features API. These all get added and Drush will create any new module files. In this case an events_feature.features.inc file which has the definition of the new image style we've added.

As another example, say you add a node type called Events that has custom fields that you want to add to your existing Feature, simply add features[node][] = events to your info file, run Features update and now you have all your events node related fields and definitions within the Feature as well as variables and other dependancies.

Alternatively, run:

drush --d fe events_feature node:events

... and the new components, dependancies and the like will get added. Important to note that using this method, add only new components that are not already in the Feature to your drush fe string, otherwise you'll get a message that there are no new components to add.

One interesting thing to do with all this is, if you are managing your local dev with Git, use Git Tower to visually see the diff changes after you run drush fu. It's a great visual learning tool and really gets you dialed in to the nuances of what goes into a Feature. You can also run drush --d fu-all to update all your Features within a site.

You can use Drush to revert a Feature which comes in handy on a remote site. Once you've pulled from Git on your remote server, simply do this:

drush --d fr events_feature

This will revert the remote Feature to your most recent version you had updated locally.

Extra, Extra...

As a bonus, I'll cover how to export static blocks. You'll need the Features Extra module for this. With Features Extra, when adding a new static block, you'll see a new field within the block's edit page called "Machine name." Once you give the block a machine name and save it, the block will now be available for export via Features.

Let's say I've created a block called My Custom Block with a machine name of my_custom_block. You can add the new components using the Features Extra syntax to your .info file as we did above as such:

features[fe_block_boxes][] = my_custom_block
features[fe_block_settings][] = block-my_custom_block

There are two parts to this, the actual block and content,fe_block_boxes and all the settings for the block itself, fe_block_settings. This might include permissions, content type, theme block region and more. Though the options are less so for Drupal 6, Drupal 7 brings a lot more settings into the block edit page itself and these are all available here for export. Now if you run drush --d fu events_feature, you'll magically see new files appear within your feature for the newly exported block.

If you get any of your syntax wrong for adding new components to the .info file, using debug mode, Drush will simply delete any bad code or syntax and you may even see some useful debug info in Terminal. If you're using Git Tower to visually track your changes, you'll immediately see where things went wrong in your diff files.

This is the tip of the iceberg with Drush and Features but it should get you thinking about how to approach this, and in the long run work smarter and faster as a Drupal Developer whether you are a Themer, Site Builder or Backend dev.


  • Drupal
  • Drush
  • Features
  • PHP
  • Drupal Planet


Comments or questions about this post?

Feel free to @reply me on Twitter!