Naming Conventions
Naming conventions serve one simple purpose: so that looking at a name is enough to guess what the thing behind it is, without having to go open the file.
1. Module Machine Names
A module's machine name is lowercase, words separated by underscores, and short enough to type without thinking twice about it — it becomes the prefix on every procedural function and hook implementation the module declares.
product_import
custom_search
weather_apiA machine name is picked once and effectively never changes afterward, since it's baked into config, hook implementations, and the database — so it's worth a moment's thought before the module is first created.
2. Class and Interface Names
Class names use StudlyCaps — each word capitalized, no underscores. An interface carries the same name as the class that implements it, with Interface appended; a trait ends in Trait, and an exception class ends in Exception.
ProductImporter
ProductImporterInterface
ProductImportException
LoggableTrait3. Method and Function Names
Class methods use lowerCamelCase. Standalone procedural functions — hooks included — use snake_case and are always prefixed with the module's machine name, which is what keeps two modules from ever declaring a function with the same name.
// Method on a class: lowerCamelCase.
public function importProducts(): int {}
public function getActiveProducts(): array {}
// Procedural function: snake_case, prefixed with the module name.
function product_import_cron() {}
function product_import_batch_finished($success, $results, $operations) {}4. Constants and Variables
Constants — whether defined with const inside a class or define() at the top of a file — are written in UPPER_SNAKE_CASE. Variables, by contrast, use lowercase snake_case, never camelCase, which is one of the more visible differences from other PHP communities' conventions.
const IMPORT_BATCH_SIZE = 50;
$product_count = 0;
$is_published = TRUE;5. Hook Function Names
A hook implementation is named after the hook it implements, with the module's machine name replacing the hook prefix: hook_cron() becomes product_import_cron(), hook_form_alter() becomes product_import_form_alter(). For the _alter hooks that target one specific form, the target form ID is inserted in the middle: hook_form_FORM_ID_alter() becomes product_import_form_node_form_alter().
/**
* Implements hook_cron().
*/
function product_import_cron() {}
/**
* Implements hook_form_FORM_ID_alter() for the node edit form.
*/
function product_import_form_node_form_alter(&$form, FormStateInterface $form_state) {}6. Twig Template File Names
Twig template files use lowercase, words separated by hyphens rather than underscores, and end in .html.twig. A more specific template — one that targets a particular content type, view mode, or display context — adds further hyphen-separated segments to the base template's name.
node.html.twig
node--article.html.twig
node--article--teaser.html.twigThis naming pattern is what Drupal's template suggestion system relies on: the more specific file, if present, wins over the more general one, without any extra registration needed.