Create a module without writing any code with Features

As you build Drupal sites, define content types, setup Views and image presets, you end up making a lot of configuration changes. One of the problems with Drupal (up to and including Drupal 7) is that content and configuration is all stored in the database. I'm sure you have experienced the real headache when you want to move the content types, views and various configuration changes from a development site to production site or to another site entirely. You end up repeating configuration changes again (and again).

Wouldn't it be nice if you could package up all of that configuration into a module? It could then act like any other module - you put it on other websites and just enable it to get all of the functionally. Or build it on a dev machine, and easily move it to the live site. Enter the Features module.

The Features module

The Features module allows you to build "features" using site building, rather than writing the actual code yourself. Each feature is a set of components for a particular use case. For example, a blog feature. You create a blog content type, a view of blog posts, an image style for blog images etc. You then build a feature with those components. This is a module that you can turn on to give you functionality when you enable it.

“The features module enables the capture and management of features in Drupal. A feature is a collection of Drupal entities which taken together satisfy a certain use-case.”
Extract from http://drupal.org/project/features

When you create a Feature, you are in fact creating a module. All the exported configuration is stored in files in the module’s directory. Just like any other module, it can be version controlled (using Git, Subversion or similar), deployed and shared.

In this tutorial, you are going to build a todo list, called Todotoday. You will start off by building the functionality without writing any code. You will then turn it into a module using Features. Our todo list will contain a set of tasks. A task is simply an item that needs to be done.

Add content type

The first thing you are going to do is to create a content type called Task. We will treat each task as a Drupal node. This will gives you tremendous flexibility if you want to extend the module, or allow other modules to interact with it.

Let’s get cracking and create the content type.

Click on Structure from the main menu and a dialog will appear. Click on Content type.


Figure 1: Structure menu

You will now see a list of current content types. Click on Add content type.


Figure 2: Content types

You will then be presented with a form to complete. You will want to call the content type Task so that when a user wants to add a new task, they will simply go to Add Content and Task. So go ahead and add Task to the name field.


Figure 3: Task content type

You will notice that the machine name is automatically filled in. A machine name is Drupal’s internal name for a content type.


Figure 4: Content type name

You want to change this and prefix it with our module name. This will help keep things organised in the database. When you have many content types, it is helpful to be able to identify which module they belong to. So let’s click edit and change the machine name to todotoday_task.


Figure 5: Edit human-readable and machine name

Next, you need to add a description. This will be displayed when a user adds a new task, so you can say something like “Task to add to todolist”. You also should change the title from “Title” to “Task”. This makes it clear to the user to add their task in the title field.


Figure 6: Description

On the left hand side of the bottom half of the form, you will see a bunch of tabs. These contain various default options for the content type. Click on Publishing options. New content types are set to Published and Promoted to front page. However, as you do not want our Todo list Tasks to end up on the front page, un-tick this option.


Figure 7: Default publishing options

Change to:


Figure 8: New publishing options

You could just save the content type now. But you need to add some fields, so click on Save and add fields.

Add Status Field

You are going to add a status field. So in Add new field, add the following:

Label: Status
Machine name: field_status
Field: List (text)
Widget: Select list


Figure 9: Add new field

After you click save, you will get a form with Field settings. Here you need to add the options for our select list. Add New, Started and Done.


Figure 10: Field settings

You will then see a bigger form with more settings. Here you want to change the default value for Status to New.


Figure 11: Default value

Add due date field
To add a date field, you need the Date module. Download it from the Date module project page. You need to enable both the Date and Date Popup module, which is supplied with the Date module download. Enable them in the modules page (admin/modules).

Add the date field. Set the following:
Label: Due date
Field: Date
Widget: Pop-up calendar


Figure 12: New date field

On the Field Settings screen, set the date attributes to Year, Month and Day only.


Figure 13: Field settings screen

Add data

Now, let’s try adding an item. Go to Content, Add Content and Task. You will be presented with our shiny new interface for adding Tasks.


Figure 14: Create task

The only problem is, you have a massive body field. This is a simple todo module, so you probably don’t need the body field. Let’s go back to edit the content type and get rid of it. Go back to the content type, edit it and edit fields. You will see the body field along with the Status, Due date and Title fields.


Figure 15: Body field

Click delete next to Body and confirm.

Now, click on Add Content and Task again. Now you have a nice simple form with Task, Status and Due date fields.


Figure 16: Add task with new fields

Let's put in some dummy tasks such as buy some milk, wash the car, walk the dog.


Figure 17: New task

Set Buy some Milk to Done, Wash the Car to Started and leave Walk the Dog as New.

Add to feature

If you go to the content list (Content -> Find Content), you will see the Tasks you just added. So far so good. Now you need to turn all this configuration into a Features module.

The first thing we need to do is to add the Feature module. Download it from the Features project page. Enable Features in the modules page (admin/modules).

Now that Features is installed, let’s use the interface to create our Todotoday feature module. Go to Structure and then Features.


Figure 18: Structure screen

The top part of the form is the basic information about the feature. Fill it in like so:


Figure 19: Features form top

The bottom part of the form is where you add the components of the feature. So far, you just have a content type. Clicking on the Edit components drop down reveals the available components. Select Content types: node and then select Task. Your form should now look like this:


Figure 20: Features form bottom

As you can see, the status field that you added has been pulled into the feature automatically.

Now you can download the feature and save it. A module that you create using Features is a lot like a custom module. This is especially true if you eventually add custom code to the module. So I prefer to save Features along side any custom modules that I create in sites/all/modules/custom. Drupal does not come with a custom directory, so if you haven't created one already, create one now.

Some people prefer to create a directory just for the Features they create instead of putting them in the custom modules directory. You can read more about this and other ways to structure your modules directory in how to structure your modules directory.

After you have added the downloaded Feature to sites/all/modules/custom and go back to Structure -> Features (admin/structure/features), will see Todotoday listed. That is the feature module you just created!


Figure 21: Manage Features screen

You will notice that it is not enabled yet. You can enable it by ticking the box and saving. Because this is actually a module, you can enable it on from the modules page (admin/modules) as well.

Now that you have a nicely packaged and contained Feature module, you can copy it to another site and simply enable it to get all of the functionality it contains.
If you use source control (Git, Subversion etc), you can add this module just like you would any other module. If you have a dev and production site, you can easily move this module and any changes to it from dev to production without having to repeat any configuration changes.

Summary

In this tutorial, you started to create a simple todo list in the Drupal UI. You then used the Features module to export the configuration to an actual module without writing a single line of code. You can of course create Content Types and Views without exporting to a module using Features. But there are big advantages in doing this. Now that all the configuration is in code, it can be treated like any other module. It can be put under source control (such as Subversion or Git) and deployed easily.

Next steps

In the next tutorial, I will walk you through how to add a View to the feature by re-exporting it. If you are not on the mailing list, jump on to ensure you don't miss it!

If you would like to learn more about creating features modules and how to take them to the next level with custom code, grab a copy of Master Drupal Module Development.

Comments

It's amazing how many developers or development teams do not commit configuration to code citing time as the reason.

Question please - does my custom module load the configuration which is then saved to the database? ie once the custom module is enabled is it no longer need because the module's configuration has transferred to the database?

Thanks...

Blair Wadman's picture

It depends on the component. For example: Fields will get saved to the database when the feature module is enable, so you can normally remove the feature. But Views do not. A view is only added to the database if a change is made in the UI.

In theory though, you should keep the feature module enabled. Features is designed so that if you disable it, all of the functionality is that is defined by it is removed. Even though this is not always the case (as with the fields example) - it is best to use Features as it is designed to be used. There is more info on this page (under "Silently" disable a feature module): https://drupal.org/node/582674

@ Blair ok thanks.

Thanks so much for this well structured and detailed tutorial. One of the best tutorials i have ever come across as someone still learning drupal. Great one!

A really amazing tutorial indeed.
Thank you very much for contributing with the drupal community with this great tutorial.

I do have some questions, i hope you can get the chance to read them:

1. Is it possible to attach js files to define module's specific behavior?
2. Is it possible to do that without modifying any code? i mean, directly from the administrator interface
3. Is it possible to manage module specific variables from the module configuration screen? Is that possible without modifying php code?

My guess is that those last two questions are impossible, but there is people insisting in that it can be done somehow... any advice?

Thx again for the wonderful article

Add new comment