Drupal: How to structure your modules directory

Ever feel like your Drupal code is becoming a disorganised mess? Most Drupal sites contain a decent number of contributed modules. Before long, you might write your own custom modules. And then you might generate Features, which are also modules. You end up with a heck of a lot of modules! You could dump them all into the modules folder, but then how will you distinguish between what is custom and what is contributed? Sure you know what your custom modules are, but you will have to search for them through that long list of all those modules. If only they could be more organised!

Organising code into relevant buckets is critical, especially as you add more and more modules to your Drupal application. After all, Drupal core is not all in the same folder! Having good organisation makes it easier to find what you need. It makes it easier to know what can be directly changed, and what needs to be upgraded from drupal.org.

I have seen a variety of different approaches and strategies to organising code across all of the Drupal projects I have worked on and they all have their pros and cons.

Where does the modules folder live?

Your modules directory could live in sites/all or sites/example.com, or both. If you are running a multi-site install, your setup will likely look like this:

  1. |--sites
  2. | |-- all
  3. | | |-- modules
  4. | | |-- themes
  5. | |-- example.com
  6. | | |-- modules
  7. | | |-- themes

In this setup, any modules and themes that can be used by any site reside in sites/all. Any modules and themes that are site specific are stored in their relevant sites folder, such as sites/example.com.

If you run a single site on a single instance of Drupal, your structure will be simplified. You only need one modules folder and one themes folder. You still may elect to have a site specific folder, which is useful if you add a second site at a later date.

The directory structure with all contrib and custom modules and themes in sites/all is as follows:

  1. |--sites
  2. | |-- all
  3. | | |-- modules
  4. | | |-- themes

It is important to note that the modules folder in sites is for contributed and custom modules only. Core modules reside in the modules folder in the root of the Drupal installation. Core modules should not be touched and you should not add any contributed or custom modules there. Why? Because it becomes a nightmare to upgrade your Drupal code if there is not a clean separation.

Now let's talk about how to structure the modules folder itself.

Custom inside Contrib

In this option, all contributed modules are inside the modules directory. The directory called custom is in the same modules folder and all custom modules are stored in there.

  1. |-- sites
  2. | |-- all
  3. | | |-- modules
  4. | | | |-- antispam
  5. | | | |-- custom
  6. | | | |-- cck

This is an improvement on having all modules in sites/all (or sites/example.com) with no further structure, but it is still not ideal. When you want to work on custom code, you have to pinpoint the custom directory along side all of the contributed modules. This might not sound difficult, but when you are doing this many times per day, it becomes a pain. This approach is partial organisation, but it does not go far enough to full organisation.

Custom and Contrib

In order to solve the problem of having the custom directory mixed in with contributed modules, you can create a directory called contrib, which sits along side the custom directory. All contrib modules then reside inside the contrib directory, as the name suggests. This provides the clean separation that we desire and makes it easy to find either contrib or custom modules.

  1. |-- sites
  2. | |-- all
  3. | | |-- modules
  4. | | | |-- contrib
  5. | | | |-- custom

Contrib, Custom, Features

Most sites over a certain size use Features to manage and deploy site building configuration. When you export a feature, all of the code is auto-generated for you. For this reason, you may consider this to be a different category to custom modules, so create a separate directory for it.

  1. |-- sites
  2. | |-- all
  3. | | |-- modules
  4. | | | |-- contrib
  5. | | | |-- custom
  6. | | | |-- features

I have seen this approach taken on most of the Drupal projects I have been involved in. There is one problem with this though - a feature can very quickly become a custom module. It is very common to export configuration for a particular area of functionality as a feature module, and then add custom code that belongs to the same area of functionality to the .module file of the feature. For example, you may have a feature that deals with articles which contain exported code for the article content type, an article view, image presents for articles etc. You may then implement hook_form_alter() for the article node form or some other bit of custom code. Is the module now a custom module, or is it still a feature?

Some people's approach to this is that as soon as custom code is added, the module gets moved to the custom directory. The problem with this is that if you are specifically looking for feature modules in the features folder, you will obviously not see the ones that have been moved to custom. You could argue that the separation between custom and features is a separation that is not required. After all, features are modules and they are custom, even if much of the code is auto- generated. They are still modules and should be considered first class custom modules with their rightful home being the custom directory.

Contrib, Custom, Features, Dev Tools

  1. |-- sites
  2. | |-- all
  3. | | |-- modules
  4. | | | |-- contrib
  5. | | | |-- custom
  6. | | | |-- dev-tools
  7. | | | |-- features

Taking this one step further to separate out any modules that are used by developers only. These modules include the likes of devel, coder etc. You probably do not want to deploy those to the live environment, so keeping them in a separate folder makes it easier to exclude them.

Contrib, Custom, Features, Dev Tools, Migration, Patches

  1. |-- sites
  2. | |-- all
  3. | | |-- modules
  4. | | | |-- contrib
  5. | | | |-- custom
  6. | | | |-- dev-tools
  7. | | | |-- features
  8. | | | |-- patches
  9. | | | |-- migration

No doubt you will need to patch contributed modules at some stage. You should have a directory with all the patches you have applied. It is common to put those in a folder outside of the Drupal application code, but putting it inside sites/all makes sense for contributed modules (and themes).

Another addition here is migration, which includes any migration related code.

My ideal setup

My ideal setup is to separate where there is a clear need to and a clear demarcation. Because of the fuzzy line between a feature module and a non-feature custom module, I would ideally keep feature modules in with custom modules and everything else is the same as the last step.

  1. |-- sites
  2. | |-- all
  3. | | |-- modules
  4. | | | |-- contrib
  5. | | | |-- custom
  6. | | | |-- dev-tools
  7. | | | |-- patches
  8. | | | |-- migration

Wrapping up

The approach you take to organise your modules will depend on the size and complexity of your Drupal project. But whatever approach you take, it is better to organise than to be disorganised. And it is normally easier to start off with a good directory structure from the start than to have to switch to one later. At the very least, start off separating contributed and custom modules into separate folders.

If you like this post, you would enjoy my weekly Drupal newsletter, where I send out tutorials on starting and getting better at Drupal development. You can sign up in the box below, where you will receive a free 7 day Starting Drupal Dev course, followed on with the weekly newsletter.

To scale the Drupal development learning curve faster, check out my book Master Drupal Development. It will help you master module development faster to become a fully fledged Drupal developer.


Conquer Drupal 8 Module Development

Don't struggle to conquer Drupal 8 module development. Action packed lessons where you will work along building your own real world modules.

20% launch discount available now!

Find out more


Comments

I suggest to keep te development tools in te sites/dev.example.com/modules/... directory instead of the sites/all/modules/... This makes it easier to see (and prove) that the dev modules don't end up at the production evironment. Dev modules are in my eyes a potential security risk for a site and should therefore not live at production.

We use a similar setup, but also move all contrib modules that we've patched to a 'modified' folder, so it's clear what we've touched.

Awesome, never thought of that. I use contrib inside custom this whole time

I really like the break down and organization of projects as well as you rationale behind doing so. An issue that I've experienced with doing this previously is that moving some projects that rely on resource and caching of files in drupal's built in registry can cause issues if they are moved. The best examples of this are Ctools, Context and Views. Having multiple copies of them or moving them on a live site can be devastating without https://drupal.org/project/registry_rebuild since the act is pretty darn close to bricking a drupal site.

Something I'm playing around with currently in terms of structuring is using https://drupal.org/project/dslm which is a symlink and core management project to help enable me to make things manageable for me as a developer but let drupal look at the same files it's expecting to find. Combining your technique with this patch to dslm https://drupal.org/node/2118957 could allow for what your trying to accomplish but make all the files (as far as drupal's concerned) live under sites/all/modules and be more a "traditional" drupal modules directory structure.

I tried moving entityreferences, but this brick my site reproducible. No idea how to solve this.

Blair Wadman's picture

Have you tried Registry Rebuild (mentioned in comment above)?https://drupal.org/project/registry_rebuild

well, I recommend to use registry rebuild module.

perfect, i have same thoughts on feature-custom separation. thanks for idea on dev-tools, i usually do gitignore on each of specific modules, but this would be even better

Great write up of the options. It never occurred to me to put a custom module inside a feature before. I resolve the problem of where a feature lives just by not putting custom modules into features.

The set up I've used most often:

|-- sites
| |-- all
| | |-- modules
| | | |-- contrib
| | | |-- custom
| | | |-- devel (git ignore this folder)

You may want to look into keeping the patches directory outside of Drupal. Your project root should be separate from your web root anyway, so keep a patches folder there. This way, you can easily update Drupal without blowing away those non-module directories.

What will be happen with my live site if my DEVEL module enable and I forget to disable it. What might be possibilities?

Really its awesome article for beginners.

Thanks to assist at basic level.

Add new comment