Skip to content

Drupal Developer Reference & Cheatsheet

DodaTech Updated Jun 6, 2026 4 min read

Learning Path

    flowchart LR
    A["Drupal Overview"] --> B["Core Concepts"]
    B --> C["Intermediate Topics"]
    C --> D["Advanced Topics"]
    D --> E["Practical Applications"]
    A --> F["You Are Here"]
    style F fill:#f90,color:#fff
  

This reference page is your quick-lookup guide for Drupal development. Every snippet is tested and production-ready.

What You’ll Find

  • Module development — .info.yml, routing, hooks, plugins
  • Entity and field API — creating content entities and fields
  • Render arrays — building page output programmatically
  • Twig templates — naming conventions and common patterns
  • Drush commands — daily operations cheatsheet
  • Security hardening snippets

Module Development

# mymodule.info.yml
name: 'My Module'
type: module
core_version_requirement: ^10
description: 'Custom module example.'
<?php
// mymodule.module — Hook implementations

use Drupal\Core\Routing\RouteMatchInterface;

/**
 * Implements hook_help().
 */
function mymodule_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {
    case 'help.page.mymodule':
      return '<p>Help text for my module.</p>';
  }
}

/**
 * Implements hook_preprocess_node().
 */
function mymodule_preprocess_node(array &$variables) {
  if ($variables['node']->bundle() === 'article') {
    $variables['attributes']['class'][] = 'article-custom';
  }
}
?>
# mymodule.routing.yml
mymodule.hello:
  path: '/hello'
  defaults:
    _controller: '\Drupal\mymodule\Controller\HelloController::hello'
    _title: 'Hello World'
  requirements:
    _permission: 'access content'

Entity & Field API

<?php
// Define a content entity type
function mymodule_entity_type_build(array &$entity_types) {
  $entity_types['product'] = new ContentEntityType([
    'id' => 'product',
    'label' => 'Product',
    'handlers' => [
      'storage' => 'Drupal\Core\Entity\Sql\SqlContentEntityStorage',
      'list_builder' => 'Drupal\Core\Entity\EntityListBuilder',
    ],
    'base_table' => 'product',
    'entity_keys' => ['id' => 'pid', 'label' => 'name'],
  ]);
}

// Create a field storage programmatically
$field_storage = FieldStorageConfig::create([
  'field_name' => 'field_price',
  'entity_type' => 'node',
  'type' => 'decimal',
]);
$field_storage->save();

// Attach field to a content type
$field = FieldConfig::create([
  'field_name' => 'field_price',
  'entity_type' => 'node',
  'bundle' => 'product',
  'label' => 'Price',
]);
$field->save();
?>

Render Arrays

<?php
// Build page output programmatically
function mymodule_custom_page() {
  return [
    '#type' => 'markup',
    '#markup' => '<h1>Custom Page</h1><p>Built with render arrays.</p>',
    '#attached' => [
      'library' => ['mymodule/styles'],
    ],
    '#cache' => [
      'tags' => ['node:1'],
      'contexts' => ['url.path'],
    ],
  ];
}

// Form API example
function mymodule_form($form, &$form_state) {
  $form['name'] = [
    '#type' => 'textfield',
    '#title' => 'Name',
    '#required' => true,
  ];
  $form['submit'] = [
    '#type' => 'submit',
    '#value' => 'Submit',
  ];
  return $form;
}
?>

Twig Templates

Template FilePurpose
page.html.twigPage-level layout (regions)
node.html.twigNode (content item) rendering
node--article.html.twigArticle content type only
node--article--teaser.html.twigArticle teaser view mode
block.html.twigBlock rendering
field.html.twigIndividual field rendering
views-view.html.twigViews output wrapper
{# node--product.html.twig #}
<article{{ attributes }}>
  <h1>{{ label }}</h1>
  <div class="product-price">{{ content.field_price }}</div>
  <div class="product-body">{{ content.body }}</div>
</article>

{# Accessing field values directly #}
{% set price = node.field_price.value %}

Drush Commands

# Cache
drush cr                      # Clear all caches

# Modules
drush en module_name          # Enable a module
drush pmu module_name         # Uninstall a module
drush pml                     # List all modules/themes

# Configuration
drush cex                     # Export configuration to YAML
drush cim                     # Import configuration from YAML
drush cedit system.site       # Edit config in terminal

# Database
drush sql:dump                # Export database
drush sql:cli                 # Open MySQL CLI
drush updb                    # Run database updates

# User
drush user:create username    # Create user
drush user:password admin pw  # Reset password
drush uli                     # One-time login link

# Content
drush node:create article     # Create a node
drush node:delete article     # Delete nodes

# Theme
drush theme:enable mytheme    # Enable theme
drush config:set system.theme default mytheme   # Set default theme

# Development
drush ev 'print "hello";'    # Evaluate PHP
drush state:set key value    # Set Drupal state

Security Hardening

<?php
// settings.php additions

// Trusted host patterns (prevents host header injection)
$settings['trusted_host_patterns'] = [
  '^example\\.com$',
  '^www\\.example\\.com$',
];

// Hash salt for password and session security
$settings['hash_salt'] = 'your-unique-random-salt-string';

// Skip file permissions check on production
$settings['skip_permissions_hardening'] = FALSE;

// Reverse proxy configuration (for CDN/Varnish)
$settings['reverse_proxy'] = TRUE;
$settings['reverse_proxy_addresses'] = ['192.168.0.1'];
?>

Common Hooks

<?php
// Preprocess hooks (alter variables before templates render)
hook_preprocess_node(&$variables)        // Alter node template variables
hook_preprocess_page(&$variables)        // Alter page template variables
hook_preprocess_block(&$variables)       // Alter block template variables
hook_preprocess_field(&$variables)       // Alter field template variables
hook_preprocess_views_view(&$variables)  // Alter Views template variables

// Alter hooks (modify data)
hook_form_alter(&$form, &$form_state, $form_id)  // Modify any form
hook_node_alter(&$node)                           // Modify node before save
hook_entity_view_alter(&$build, $entity)          // Modify entity display
?>

Common Mistakes

  1. Assuming all features work identically — always check browser/version compatibility.
  2. Skipping documentation — reference docs exist for a reason; consult them.
  3. Not testing edge cases — your setup may differ from tutorials.
  4. Overlooking security — always validate inputs and follow best practices.
  5. Copy-pasting without understanding — type code yourself to build real knowledge.

What’s Next

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro