Drupal 9: Selecting Machine Names For Content Entities And Fields

1st August 2021 - 24 minutes read time

Naming things is hard[citation needed] and there are a lot of things that you can name when configuring a Drupal site. Picking the right machine names for the different parts of Drupal can make your life easy in the long run. Changing labels is simply a case of tweaking the label in the interface, or through configuration updates. The issue is that once you decide on a machine name for something in Drupal it's pretty much set in stone forever.

The machine names you pick are often used in database tables, paths, interface elements and pretty much anywhere it is used. Changing entity or field machine names at a later date is difficult and can mean writing complex code or using migrations to achieve.

I have built a lot of Drupal sites over the years and done detailed audits on quite a few as well. This experience has given me a lot of insight on how to set up by machine names in Drupal. I have seem some horrific naming practices and poorly configured sites and in my experience there is a correlation between poorly named things in Drupal and bugs caused by those poor choice of names.

As far as I can tell the drupal.org documentation doesn't actually cover this aspect of setting up Drupal. It does address naming conventions in code and modules as part of the coding standards, but not with machine names for content and fields.

Recently, I got into a discussion with a couple of other Drupal developers about content entities and fields, what to name them, and what to avoid when reusing fields. Surprisingly few people have written about naming conventions in Drupal, despite the fact that it has such an effect on the life cycle of the site itself. I thought I would write down some of the conventions I use when naming things and some of the best practices when reusing fields within a Drupal site.

I will start by addressing the naming of content entities.

Naming Content Entities

Content entities aren't just the configurable content types you have in Drupal, although they play a big part. It also includes things like content blocks, taxonomy terms, paragraphs or anything else that you can configure and start making content. Drupal gives you 32 characters to name your content entities so you have a bit of space to play with.

When you create a content type Drupal will automatically create a machine name for you.

Creating a new content type in Drupal

Click on the edit link here to expand the machine name and ensure that it meets your naming requirements. This is much the same for different types of content entity that you might create around the site. This machine name expand functionality is built into most forms like this.

Creating a new content type in Drupal and editing the machine name.

When you set out to name content types in Drupal you must think about the long term use of that content. As an arbitrary example, let's say that you create a content type to store resources for university students in the first year. You can easily name this content "First year resources", which then had the machine name of first_year_resources. This proves popular and so you decide to roll the feature out to second year students as well. This means you either need to create a new content type called second_year_resources or continue to use the first_year_resources content type for second year students. Either way, if you then need to roll out the same feature to third year students then you will have multiple content types doing the same thing or a single content type with a name that doesn't fit its purpose.

This will cause a problem behind the scenes as your developers will be faced with one of two situations. They will either have a content type called "first_year_resources", that isn't just for first years. Or they will have multiple content types that are essentially doing the same thing and have lots of duplicated templates and configuration. In the long run this causes frustration and the confusion will ultimately can lead to mistakes (and bugs).

The solution to this situation would be to start out with a content type called "Resources", which can then be expanded to other years or courses when needed. This creates the machine name of "resources", which is easily understood by developers. This single content type can then be themed easily and rolled out to different users. It can be easily segmented into lists by the use of taxonomy terms. Once the content type and code is in place, it doesn't need to be changed if you want to create resources for other types of users. 

Fundamentally, you should be thinking about the underlying data structures of the content you are creating. I have seen multiple Drupal sites where a content type of "News" has been created and at a later date another content type called "Press Release" is created. The difference between an item of news and a press release is irrelevant to how the data is stored as they will both contain a title, some body copy and maybe some taxonomy terms. In one particular example I worked on a site that had no less than 5 different content types that were just for news related content. This caused a lot of confusion as even the users didn't know what sort of news item they should be creating. Content creators would often create the wrong news type and then had to copy/paste the content to create a different type of news item.

What the developers intended was that press releases would appear in one list and news items would appear in another, and so on. Instead of creating a single content type for news and using taxonomy terms to filter, they created multiple versions of the same thing. The problem is that because of the similarity of the data they will probably have duplicate templates and preprocess hooks to ensure the presentation is correct. A better approach, in my opinion, is to create a content type called "Article" and then use taxonomy to segment that content type into different lists. Permissions for different news types can be achieved by using taxonomy access control.

The same things apply to the other types of content entity in Drupal. They key thing to remember is that things like content blocks and paragraphs are meant to be re-used across the site. This means that you must adhere to the rule of 'name once, use many' when creating them.

It is quite easy to fall into the trap of setting up a paragraph with the name of 'Two column content' and then need to alter that paragraph to use different numbers of columns in different situations. Having a paragraph with that name and can have anywhere between one and four columns makes little sense and will confuse developers as well as editors of the site.

The rule is, don't get too specific. I have seen plenty of situations where a content type called "Homepage" was created that is only ever used to present the homepage. Or a content block called "Copyright" that is only ever used to print out the copyright statement at the bottom of the page. This sort of thing creates baggage that your Drupal site needs to drag along with it during its life. There are better solutions to this, especially in Drupal 9 with the layout system or the configuration pages module.

Paragraphs are quite often abused in Drupal sites. I once inherited a Drupal site that had over 45 types of paragraphs. I didn't even know the paragraph administration page was paginated until I saw that mess! The root of the issue was that the original developer had created 8 different variants of a "Hero" paragraph, each containing just an image field, but with a slightly different way to display the content. When the author wanted to change the type of hero on a given page they had to remove one paragraph and add another one with the correct setup. This really should have been a single paragraph called Hero that contained fields used to control the output. All this complexity could have been avoided through the use of a small amount of templating or preprocess logic.

Here are some tips to have best practice around naming content entities.

  • Don't make the content entities specific to a single type of use. This means avoiding names "Two columns" where more columns might be used or a content type called "Homepage".
  • Don't use similar looking names. For example, avoid using Event and Events as content types on the same site. Also, avoid paragraphs called "Hero" and "Hero wide" as this can easily be accomplished via templating.
  • Don't use the site name or project name for the name of the entity. This is generally a good rule to follow anyway as giving your content types site only names will restrict re-use on other projects.
  • Do keep the name it short and simple.
  • Do describe what the content entity is.
  • Do try to avoid the use of underscores in your content entity names.
  • Do use abbreviations to keep the name short, but still avoid the use of similarly named entities and difficult to understand (or spell) names.

Naming Fields

One of the most critical things to name correctly is the field as this is where all of your data will be stored. Developers will probably interact with fields the most so having them named correctly is critical to the development and maintenance of your site.

Whilst content entities have a single item of configuration, fields are created using two. There is the field storage configuration that tells Drupal what and how to store the data relating to the field. In addition to this there is a field instance configuration that is used when a field is connected to a content entity as well as any custom configuration the field might need.

Most difficulties I have found with field names in Drupal is when the field is either named counter to its function, or it named quite similarly to another field. You should be looking at creating field names that describe what their function is and what they are connected to. This means creating fields with a format like the following.

field_<content entity type>_<field machine name>

As an example, let's say that you created a field called field_page_subtitle. This is immediately obvious that the field belongs to the page content type and contains some sort of string. This means that when I want to load in the value of field_page_subtitle I just need to reference the value, rather than load any files or entity references. Similarly, for a paragraph field containing a title the field name should be field_paragraph_title.

Adding the type of content that is being stored to the field can be helpful in understanding its function, although this shouldn't be a blanket rule. For example, adding a field called field_page_title or field_user_first_name is fine as people will understand that the field contains a string of some kind. Fields that store data like dates or images should ideally be named to show that they contain a different type of data. For example, if you create a field for the start date of an event it therefore makes sense to call it field_event_start_date. If the field also contains the time then you might call the field field_event_start_datetime to show that it contains more than just the date.

Similar named fields can cause confusion, so you should endeavour to keep your fields as unique as possible. I remember seeing one site I was auditing that had a field called field_image, which was fine, but the same content type had a field called field_images (with an extra 's'). There were quite a number of bugs associated with just these two fields having slightly different names, despite them clearly having the same function (ie, storing images). One of the fields should have been called field_page_hero in order to show where the image is used.

Just like content type machine names you have 32 characters to use, although this includes the prefix "field_" at the start, so you actually have a few less characters to play with.

Creating a new field in Drupal and editing the machine name.

One thing to watch out for is when you create a long field name on a content entity that also has a long name. Although the maximum length of the field is 32 characters, the maximum length of the table name is 64 characters if MySQL is being used. A good example of this is the taxonomy tables as the taxonomy term revision table must be prefixed with "taxonomy_term_reivsion_field". If that length, plus the length of your field name exceeds 64 characters then Drupal will reduce the prefix to "taxonomy_term_r__" and convert the field name to a hash of its name. This is what has happened if you spot any tables with a name like "taxonomy_term_r__2de1caf063" in your database.

Here are some tips to have best practice around naming fields.

  • Don't use similar field names. Don't use field_image and field_images as this is bound to cause confusion and errors in the long run.
  • Don't name your fields with regards to the project or site as this prevents their re-use on other projects.
  • Do describe what the field is for in the name. If it is storing a name call it 'name'.
  • Do include the type of data being stored in the field, but only if it makes sense to do so.
  • Do add the name of the content entity the field is connected to. For example, a field that stores a name field on a User entity would be called field_user_name.
  • Do keep the field name to a minimum, especially if it's being used on content entities with long names like taxonomy terms or paragraphs.

Re-Using Fields

Finally, after naming content entities and fields it is worth thinking about re-using fields. Drupal will allow you to add the same field to different types of the same content entity. This means that the field you created for a Page content type can be re-used on an Article content type. You can't share fields between different types of entity, so you can't add the same field to a paragraph and a content type.

If you intend to re-use a field then you should think about making the name of the field more generic. For example, let's say that you have a field that is used store the sub title as a text field on a Page content type. If you intend to re-use this field then you can name it with the generic content entity name instead of the content type. In this instance the field would be called field_node_subtitle.

It is also acceptable to leave out the content entity name in the field name. Drupal itself does this a lot of fields like field_comments or field_tags, which are part of the standard Drupal install profile. The fact that you can't share the field between different content entities means the confusion is somewhat reduced.

I would, however, still try to keep name the field in line with the type of content entity being used. For example, instead of field_page_subtitle you would call it field_node_subtitle to show that this is a node field. This will really help if you start dealing with entity relations as you might have node, paragraph, media and taxonomy entities all in the same context.

To understand re-use correctly, it is important to understand how a field is stored in Drupal. As I mentioned above there is a field storage configuration that tells Drupal the data type of the field and a field instance configuration that tells Drupal that this field is attached to a certain content entity. Drupal keeps track of field re-use by having one storage configuration and multiple field instance configurations. A single table in the database will be used for the field, even if it is present on multiple content entities.

The single table approach to data storage is an important consideration in the re-use of fields on your site. If you add a field to more than one content entity, then both content entities will store data in the same table. If you are happy with different content items writing data to a single table then that's fine.

Before you go adding the same field across all of your content entities you need to think about how they will be used. What you want to do is add the same field (i.e. with the same form and function) to different content entities in order to duplicate functionality. You can quite easily create confusion when you have a field on one content type that does one thing, and change the label or template of the field on another content type to do something else. This means that developers and users have to know that a field in a certain context does something different.

It is quite tempting to add a field to another content entity and change the label. For example, you might have a "subtitle" field on a content type and re-use it, but change the label to "author name". Although this is still a text field what you have essentially done here is change the function of that field. Developers might get confused as to why a field called field_node_subtitle has is being used to store author names.

This difficulty goes beyond the label though as it a developer may create a twig template for a field and find that they have to add additional logic to stop the template being used for fields on certain content types. Changing what the field is doing in other types and that can cause confusion, which will ultimately lead to bugs.

Whilst it is also possible to alter the output of the field for each content type it's probably a good idea to keep them the same. Again, try to make the field behave the same everywhere it is used. This feeds back into the "create once, use many" way of thinking.

Common fields that share functionality like titles, hero images, taxonomy terms, or even comments are good candidates for sharing between content entities. They generally stay the same between different types of content. It is essential to have the same field on different content entities act and behave the same.

Here are some tips on maintaining best practice on reusing fields.

  • Do re-use the field if it will have the exact same form and function wherever it is used.
  • Do think about the long term use of the field. If you re-use a number field on a content entity and that needs to be changed to a text field then you will need to be careful with that change. You need to write some migration code, but only for that field in a certain context.
  • Don't change the form or function of the field if it is re-used on a different content entities. This includes changing the label of the field as this can be confusing to users and developers alike.
  • Don't change the cardinality (i.e. number of items) of the field after the fact as this will change the cardinality for all fields of that type. This won't delete any data but will prevent items from appearing in content forms, which can lead to data loss if the item is saved.

Conclusion

This can be a complex topic, but the general rule is to keep things as simple as possible. Name things according to their function and don't alter things to introduce surprises as no one will thank you in the future. Avoid confusing names and situations and don't always accept the auto-generated machine name that Drupal gives you.

When planning Drupal content entities and fields I always think about the phrase "create once, use many". This means that a single item of content can be re-used around the site without the users having to manually add it.

Think about the long term use of the entity or field and what developers will find. Analyse the bugs and issues on your site to see if they are connected to poorly named elements or re-used fields. You might be able to solve these problems by changing names or removing confusing fields.

There is also a Drupal module available called Naming Conventions that deals with some aspects of what I have talked about here. This module is currently Drupal 8 only, but includes the ability to disable the machine name autocomplete field and to add help about the naming conventions in use to different routes on the site. It won't enforce the naming conventions though, that is still up to you, but it will help educate developers on how to name things.

Have I missed anything out here? What rules do you use in your Drupal sites when naming content entities and fields? Have you seen any bugs created from poorly named fields? Please comment below and let me know. Also, feel free to use these tips in your developer documentation.

Comments

Permalink

Thanks Theodoros. I hadn't seen that page before but it looks like we have reached the same conclusions through our experience with the platform. Good to know I'm not alone in my thinking :)

Permalink

Thanks for this thoughtful insights! There's another thing that comes to mind when naming e.g. entity types or bundles: singular or plural? I'm alway struggeling with this :-)

Boris (Thu, 08/05/2021 - 17:13)

Permalink

I'm glad you found it informative :)

To answer your question, I would name things in the singular.

That would fit into (some!) of the table naming syntax in Drupal like the "node" table as well as other content types that you get out of the box (Page, Article).

Also, names like "Events" or "Pages" would be a poor name as you would create a single instance of an "Events" content type. Unless, of course, the site is using it to display a View, but that fall into the "single use" policy and it should really be a "View" page with an embedded View.

Permalink

Great tips, thanks for sharing! I will certainly use some in naming my entities creating my next Drupal project.

Robert Roose (Fri, 08/06/2021 - 20:25)

Permalink

Thank you!!

Great ideas to not geting confused by yourself some years after building a site.

I find usually limited by the 32 characters limit on fields, specially if placing the bundle or entity type as in 'field_node_image' and wanted to share my trick to avoid t'he 'field_' part.

On d7 it was possible to create fields named 'node_image' with drush.

On d8-9 I usually create the two config yml files without the 'field_' part and then 'drush config-import'.

It takes something around two extra minutes per field but everything is a bit simpler and cleaner then, from a developer point of view.

 

Marc (Thu, 08/12/2021 - 09:19)

Permalink

Thanks a lot for this really good article.

If I can share some tips and opinion too.

In the Field UI module you can configure the field prefix https://git.drupalcode.org/project/drupal/-/blob/9.2.x/core/modules/fie…. But there is no UI (to what I know) to change that. You can only change it by editing the YML then reimporting.

Also wanting to say that thinking ahead field reuse can also save time and maintenance when configuring parts like Views or Search API indexes.

Cheers!

Grimreaper (Thu, 08/19/2021 - 20:30)

Add new comment

The content of this field is kept private and will not be shown publicly.