Module 4.5 – Drupal Coding Standards

Drupal Coding Standards are a shared rulebook for how Drupal code should be written. They make sure that code written by thousands of developers looks consistent, is easy to read, secure, and maintainable.

Think of it like traffic rules. Everyone follows the same rules so things do not crash.

1. Technical explanation

Drupal coding standards are based on:

  • PHP standards (PSR where applicable)
  • Drupal Core conventions
  • Security best practices
  • Performance and maintainability principles

These standards are enforced in real projects using:

  • PHP CodeSniffer (phpcs)
  • Drupal Coder module ruleset

Acquia exams test whether you:

  • Recognize correct Drupal-style code
  • Can spot bad practices
  • Choose the safest and most maintainable option

Acquia is not testing memorization. It is testing judgment.

Security implication:
Consistent standards reduce injection risks, unsafe globals, and accidental data leaks.

Performance implication:
Standardized code encourages caching, service usage, and testability.


2. PHP Coding Standards in Drupal

Namespaces and classes

namespace Drupal\example_module\Controller;

use Drupal\Core\Controller\ControllerBase;

class ExampleController extends ControllerBase {
  public function content() {
    return ['#markup' => $this->t('Hello World')];
  }
}

Why this is correct:

  • Uses a namespace
  • Class name matches file name
  • Extends ControllerBase
  • No global functions

Bad example

class example_controller {
  function content() {
    return 'Hello';
  }
}

Why this is wrong:

  • No namespace
  • Wrong class naming
  • No return render array
  • Not translatable

Exam trap:
If you see plain strings returned instead of render arrays, it is usually wrong.


Methods and visibility

Drupal requires explicit visibility.

Good:

public function build(): array {
  return [];
}

Bad:

function build() {
  return [];
}

Why:
Explicit visibility improves readability and prevents accidental overrides.


3. Drupal-Specific Standards

Hooks

Hooks are procedural by design and are allowed only in specific places.

Allowed:

function example_module_help($route_name, $route_match) {
  if ($route_name === 'help.page.example_module') {
    return t('Help text');
  }
}

Why this is correct:

  • Hook functions must be procedural
  • Function name matches module name

Not allowed:
Putting business logic inside hooks.

Exam trap:
Hooks are glue code, not logic containers.


Controllers

Controllers must:

  • Return render arrays or responses
  • Use dependency injection

Good:

class ExampleController extends ControllerBase {
  public function page(): array {
    return ['#markup' => $this->t('Example')];
  }
}

Bad:

public function page() {
  echo 'Example';
  exit;
}

Security implication:
Echo and exit bypass Drupal rendering and security layers.


Plugins

Plugins must:

  • Use annotations
  • Extend correct base classes

Example:

/**
 * @Block(
 *   id = "example_block",
 *   admin_label = @Translation("Example block")
 * )
 */
class ExampleBlock extends BlockBase {
}

Exam trap:
Missing annotations means the plugin will not be discovered.


4. File and Directory Naming Conventions

PHP files

  • Class name must match file name
  • One class per file

Correct:

ExampleController.php

Incorrect:

example.controller.php

Module structure

example_module/
  src/
    Controller/
    Plugin/
    Form/

Why:
Autoloading depends on predictable structure.


5. YAML Standards

.info.yml

Good:

name: Example Module
type: module
core_version_requirement: ^10
package: Custom

Bad:

Name: example

Why:
YAML keys are case-sensitive.


.routing.yml

Good:

example_module.page:
  path: '/example'
  defaults:
    _controller: '\\Drupal\\example_module\\Controller\\ExampleController::page'
    _title: 'Example'
  requirements:
    _permission: 'access content'

Security implication:
Permissions must always be declared.

Exam trap:
Missing permissions is always wrong.


.services.yml

Good:

services:
  example_module.example_service:
    class: Drupal\example_module\ExampleService

Why:
Services must be defined to be injected.


6. Procedural Code vs OOP

When procedural is allowed

  • Hooks
  • .module file glue code

When OOP is required

  • Business logic
  • Controllers
  • Forms
  • Services

Exam rule:
If logic is reusable or testable, it belongs in a service.


7. Dependency Injection Standards

Correct

public function __construct(LoggerChannelFactoryInterface $logger_factory) {
  $this->logger = $logger_factory->get('example');
}

Why:

  • Testable
  • Replaceable
  • Clear dependencies

8. Static Calls (\Drupal::)

Allowed

  • Legacy glue code
  • Very small scripts

Not allowed

  • Controllers
  • Services
  • Plugins

Bad:

\Drupal::database()->select('node');

Good:
Inject the database connection.

Exam trap:
Static calls are a last resort.


9. Logging, Errors, and Messaging

Logging

Correct:

$this->logger->error('Something failed');

Incorrect:

print 'Error';

Security implication:
Do not expose internal errors to users.


Messaging

Use:

$this->messenger()->addStatus($this->t('Saved successfully'));

Never:

echo 'Saved';

10. Commenting and Documentation

File header

/**
 * @file
 * Provides example functionality.
 */

Function documentation

/**
 * Builds the example page.
 *
 * @return array
 *   Render array.
 */

Why:
Helps IDEs, reviewers, and future developers.


11. Common Violations in Real Projects

  • Logic inside hooks
  • Static service calls everywhere
  • Missing permissions
  • Hardcoded strings
  • No dependency injection

Exam trap:
The answer with fewer shortcuts is usually correct.


12. How Acquia Tests Coding Standards

Scenario-based questions:

  • Which implementation is more Drupal-like
  • Which code is more secure
  • Which solution is more maintainable

They test principles, not syntax memorization.


Final Exam Revision Checklist

  • Uses namespaces and PSR structure
  • No echo or exit
  • Render arrays returned
  • Permissions defined
  • Services injected
  • Hooks used only as glue
  • Logging instead of printing

One-Sentence Takeaway

Drupal coding standards exist to make code secure, readable, testable, and predictable across teams.

Quick Mental Checklist for the Exam

Is it secure
Is it injectable
Is it testable
Is it Drupal-style
Is it future-proof