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
- https://www.drupal.org/u/kimpepper (2025-04-28)
- https://www.drupal.org/u/drunken-monkey (2025-05-04)
- 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
- Classes and interfaces should use UpperCamel naming.
- 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.
- 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.]
- 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.
- Names should not include "Drupal".
- Class names should not have "Class" in the name.
- Interfaces should always have the suffix "Interface".
- Test classes should always have the suffix "Test".
- Protected or private properties and methods should not use an underscore prefix.
- 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
- Classes and interfaces should use UpperCamel naming.
- 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.
- 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.]
- 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.
- Names should not include "Drupal".
- Class names should not have "Class" in the name.
- Interfaces should always have the suffix "Interface". Accordingly, non-interfaces should never have the suffix "Interface".
- Traits should always have the suffix "Trait". Accordingly, non-traits should never have the suffix "Trait".
- Test classes should always have the suffix "Test". Accordingly, non-tests should never have the suffix "Test".
- Protected or private properties and methods should not use an underscore prefix.
- 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
Create this issue in the Coding Standards queue, using the defined templateAdd supportersCreate a Change RecordReview by the Coding Standards Committee- Coding Standards Committee takes action as required
Discussed by the Core Committer Committee, if it impacts Drupal Core- Final review by Coding Standards Committee
- Documentation updates
- Edit all pages
- Publish change record
- Remove 'Needs documentation edits' tag
- If applicable, create follow-up issues for PHPCS rules/sniffs changes
For a full explanation of these steps see the Coding Standards project page
Issue fork coding_standards-3521443
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:
- 3521443-Traits
changes, plain diff MR !9
Comments
Comment #2
godotislateComment #3
kim.pepperComment #4
drunken monkeySeems reasonable.
Comment #5
acbramley commentedSounds good, should we change the "should always" in the standards to "must" if we're going to enforce this?
Comment #6
godotislateI 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?
Comment #7
godotislateWith three supporters, I think this is OK to go to RTBC.
Comment #8
acbramley commentedFrom 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?
Comment #9
quietone commentedI 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.
Comment #10
godotislateI 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".
Comment #11
godotislateComment #12
godotislateComment #13
godotislateI made the proposed changes to Trait and Interface rules per #8 after all.
Comment #14
acbramley commentedAhh yes, all good with that then. I think enforcing the Interface side would be a separate issue (potentially just in coder?)
Comment #15
quietone commentedThis came up in the last meeting and there were no objections, #3541070: Coding Standards Meeting Wednesday 2025-08-27 0900 UTC.
Comment #16
jonathan1055 commentedThis 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.
Comment #17
quietone commentedThere were no objections to this at the last core committer meeting.
Comment #19
quietone commentedThis just needs someone to confirm that the MR matches the changes in the issue summary.
Comment #20
quietone commentedThe 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"
Comment #21
bbralaCoder issue is al gucci.
I think the proposed text changes are good.
We also need a follow up issue to add
Generic.NamingConventions.TraitNameSuffixsniff to core.Comment #22
quietone commentedCreated the core issue, #3565629: Enable Generic.NamingConventions.TraitNameSuffix
Comment #23
borisson_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.
Comment #24
jonathan1055 commentedThis 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.
Comment #26
quietone commentedThanks!
This is enforced in Coder 9. The core issue is [#/3565629]