Problem/Motivation

Traits should always have the suffix "Trait". This is a rule that mirrors the rule that interfaces always have the suffix "Interface".

There are 4 traits in Drupal core that do not end in Trait. 3 of them are test traits:

Drupal\Core\Menu\MenuLinkFieldDefinitions
Drupal\Tests\dblog\Functional\FakeLogEntries
Drupal\Tests\link\Traits\LinkInputValuesTraits
Drupal\Tests\workspaces\Functional\WorkspaceTestUtilities

Benefits

In #3502913: Add a fallback classloader that can handle missing traits for attribute discovery, a classloader was introduced to prevent reflection on classes with missing traits (for example, classes that use traits from uninstalled modules) during plugin discovery by PHP attributes. The detection of missing traits relies on whether the name of class/interface/trait being loaded ends in "Trait". There's no way otherwise to determine what is being loaded, so it is possible for the detection to fail and result in PHP fatal error.

The need for trait detection specifically will presumably go away in PHP 8.5, where missing traits will cause a catchable exception to be thrown instead of resulting in a fatal error. This change in PHP has already been committed. However, it may be a while before Drupal core supports a minimum of PHP 8.5.

Three supporters required

  1. https://www.drupal.org/u/kimpepper (2025-04-28)
  2. https://www.drupal.org/u/drunken-monkey (2025-05-04)
  3. https://www.drupal.org/u/acbramley 2025-05-26)

Proposed changes

Provide all proposed changes to the Drupal Coding standards. Give a link to each section that will be changed, and show the current text and proposed text as in the following layout:

1. Class Methods and Properties

Current text
  1. Classes and interfaces should use UpperCamel naming.
  2. Methods and class properties should use lowerCamel naming. In Drupal 8, properties of configuration entities are exempt of these conventions. Those properties are allowed to use underscores.
  3. If an acronym is used in a class or method name, make it CamelCase too (SampleXmlClass, not SampleXMLClass). [Note: this standard was adopted in March 2013, reversing the previous standard.]
  4. Classes should not use underscores in class names unless absolutely necessary to derive names inherited class names dynamically. That is quite rare, especially as Drupal does not mandate a class-file naming match.
  5. Names should not include "Drupal".
  6. Class names should not have "Class" in the name.
  7. Interfaces should always have the suffix "Interface".
  8. Test classes should always have the suffix "Test".
  9. Protected or private properties and methods should not use an underscore prefix.
  10. Classes and interfaces should have names that stand alone to tell what they do without having to refer to the namespace, read well, and are as short as possible without losing functionality information or leading to ambiguity. Notes:
    • If necessary for clarity or to prevent ambiguity, include the last component of the namespace in the name.
    • Exception for Drupal 8.x: due to the way database classes are loaded, do not include the database engine name (MySQL, etc.) in engine-specific database class names.
    • Exception for test classes: Test classes only need to be unambiguous within the context of the module they are testing.
Proposed text
  1. Classes and interfaces should use UpperCamel naming.
  2. Methods and class properties should use lowerCamel naming. In Drupal 8, properties of configuration entities are exempt of these conventions. Those properties are allowed to use underscores.
  3. If an acronym is used in a class or method name, make it CamelCase too (SampleXmlClass, not SampleXMLClass). [Note: this standard was adopted in March 2013, reversing the previous standard.]
  4. Classes should not use underscores in class names unless absolutely necessary to derive names inherited class names dynamically. That is quite rare, especially as Drupal does not mandate a class-file naming match.
  5. Names should not include "Drupal".
  6. Class names should not have "Class" in the name.
  7. Interfaces should always have the suffix "Interface". Accordingly, non-interfaces should never have the suffix "Interface".
  8. Traits should always have the suffix "Trait". Accordingly, non-traits should never have the suffix "Trait".
  9. Test classes should always have the suffix "Test". Accordingly, non-tests should never have the suffix "Test".
  10. Protected or private properties and methods should not use an underscore prefix.
  11. Classes and interfaces should have names that stand alone to tell what they do without having to refer to the namespace, read well, and are as short as possible without losing functionality information or leading to ambiguity. Notes:
    • If necessary for clarity or to prevent ambiguity, include the last component of the namespace in the name.
    • Exception for Drupal 8.x: due to the way database classes are loaded, do not include the database engine name (MySQL, etc.) in engine-specific database class names.
    • Exception for test classes: Test classes only need to be unambiguous within the context of the module they are testing.

Remaining tasks

  1. Create this issue in the Coding Standards queue, using the defined template
  2. Add supporters
  3. Create a Change Record
  4. Review by the Coding Standards Committee
  5. Coding Standards Committee takes action as required
  6. Discussed by the Core Committer Committee, if it impacts Drupal Core
  7. Final review by Coding Standards Committee
  8. Documentation updates
    1. Edit all pages
    2. Publish change record
    3. Remove 'Needs documentation edits' tag
  9. If applicable, create follow-up issues for PHPCS rules/sniffs changes

For a full explanation of these steps see the Coding Standards project page

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

godotislate created an issue. See original summary.

godotislate’s picture

Issue summary: View changes
kim.pepper’s picture

Issue summary: View changes
drunken monkey’s picture

Issue summary: View changes

Seems reasonable.

acbramley’s picture

Issue summary: View changes

Sounds good, should we change the "should always" in the standards to "must" if we're going to enforce this?

godotislate’s picture

Issue summary: View changes
Status: Active » Needs review

Sounds good, should we change the "should always" in the standards to "must" if we're going to enforce this?

I don't have much opinion on this either way, but the current language is a copy of the rules for interfaces and test classes.

I added the CR with the existing language, but I'm open to changing to must if that's preferred. If so, should the language for interface and test classes be changed as well?

godotislate’s picture

Status: Needs review » Reviewed & tested by the community

With three supporters, I think this is OK to go to RTBC.

acbramley’s picture

Accordingly, non-traits should never have the suffix "Trait".

From the CR, this is not enforced for Interface. I tested this locally and can have a TestInterface class which isn't an interface. Do we need to add this?

quietone’s picture

I renamed an interface and trait in core and then ran the commit-code-check script. In the results was this warning.

14 | WARNING | Interface names should always have the suffix "Interface"

There was not a similar warning for the trait. It does seem a sniff change is needed.

godotislate’s picture

From the CR, this is not enforced for Interface. I tested this locally and can have a TestInterface class which isn't an interface. Do we need to add this?

I think it would make sense for both interfaces and traits, so if it's not too much scope creep, I'm for adding it to interfaces as well. But it is more important for traits because we do trait detection in #3502913: Add a fallback classloader that can handle missing traits for attribute discovery based on whether the what's being loaded ends in "Trait".

godotislate’s picture

Issue summary: View changes
godotislate’s picture

Issue summary: View changes
godotislate’s picture

I made the proposed changes to Trait and Interface rules per #8 after all.

acbramley’s picture

But it is more important for traits because we do trait detection

Ahh yes, all good with that then. I think enforcing the Interface side would be a separate issue (potentially just in coder?)

quietone’s picture

Issue summary: View changes

This came up in the last meeting and there were no objections, #3541070: Coding Standards Meeting Wednesday 2025-08-27 0900 UTC.

jonathan1055’s picture

Issue summary: View changes

This was set to RTBC three months ago, but I would like to suggest a slight extra, to keep the "Test" bullet-point consistent with the "Trait" and "Interface" wording. It needs Accordingly, non-tests should never have the suffix "Test"
I have put this in the issue summary.

quietone’s picture

Issue summary: View changes

There were no objections to this at the last core committer meeting.

quietone’s picture

This just needs someone to confirm that the MR matches the changes in the issue summary.

quietone’s picture

The comment above is wrong, in the last meeting longwave reviewed the MR and said it was fine, #3549265: Coding Standards Meeting Wednesday 2025-10-29 0900 UTC.

Created a coder issue, #3557537: Enforce traits should always have the suffix "Trait"

bbrala’s picture

Coder issue is al gucci.

I think the proposed text changes are good.

We also need a follow up issue to add Generic.NamingConventions.TraitNameSuffix sniff to core.

quietone’s picture

borisson_’s picture

Text changes are good, as well as the followup being there already. I think that means this one can go in?

I noticed in the issue that was committed today that we're moving to 1. 1. 1. as number system and that we have the more traditional 1. 2. 3. here, should we change that as well for this block? It should hopefully make new additions to this block easier.

jonathan1055’s picture

This is nothing to do with the question on #23 but on Gitlab Templates we've recently finished the issue to allow testing of documentation site updates, where the merge request contains changes to any .md files. The original d.o. issue https://www.drupal.org/project/gitlab_templates/issues/3426311 #3426311: Allow testing documentation pages via MRs, is now migrated to Gitlab Issues

If the MR pipeline is being run in the "issue" namespace, which happens when non-maintainers make commits to the MR branch, then the "pages" job will be added to the pipeline. If the pipeline is being run in the "project" namespace (which happens if a maintainer makes the MR commit) then to protect the real site the pages job is not added. For maintainers to test the doc changes there are instructions on how to run a pipeline in the "issue" namespace.

So you should be able to test these changes to the documentaion page now, and view the generated updated page before you merge.

  • quietone committed cf87249d on main
    feat: #3521443 Traits should always have the suffix Trait
    
    By:...
quietone’s picture

Status: Reviewed & tested by the community » Fixed
Related issues: +#3565629: Enable Generic.NamingConventions.TraitNameSuffix

Thanks!

This is enforced in Coder 9. The core issue is [#/3565629]

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.