@me/changelog: Drupal (Front End)
As a process to get a Drupal certification that is being pushed by work in a very rushed fashion (we're talking < 2 week prep on top of client deadlines). I'd probably be fine taking the test, but re-reviewing some concepts just in case. The following text emojis (see also: kaomoji) sum up some of my feelings on it:
(¬_¬) "( – ⌓ – ) (ᵕ—ᴗ—) (¬`‸´¬) ∘ ∘ ∘ ( °ヮ° ) ?
I'm just... tired yall.
Preprocess Functions Scraps
1function mytheme_preprocess_node(&$variables) {
2$node = $variables['node'];
3$variables['my_custom_var'] = $node->get('field_summary')->value;
4}
Syntax
mytheme_preprocess_HOOK(&$variables)
$variables contain everything available in the template
Setting a custom variable
$variables['my_var'] = 'some value';
Accessing current node
$variables['node']
Accessing field values
$variables['node']->get('field_name')->value
Wrapper element attributes object
$variables['attributes']
Common use
Adding body classes, passing config values to templates, transforming data before render
Compare
hook_preprocess (all templates)
hook_preprocess_HOOK (specific template)
Drupal Behaviors
1// Drupal behavior pattern
2Drupal.behaviors.myBehavior = {
3 attach(context, settings) {
4 once('my-behavior', '.my-selector', context).forEach((el) => {
5 // code
6 });
7 }
8};
Review Concepts
Attach and detach methods
Why behaviors exist: re-fire on AJAX-loaded content, unlike $(document).ready()
context parameter: the DOM element being processed (not always document)
settings parameter: values passed from PHP via drupalSettings
once() utility to prevent duplicate behavior attachment
jQuery once vs native Drupal once (changed in Drupal 9.2+?)
Declaring JS in mytheme.libraries.yml
dependencies: declaring core/drupal , core/once , core/jquery
minified: true flag
header: true to load in <head> (usually avoid)
Passing PHP data to JS via #attached['drupalSettings']
JS aggregation in production
Views
Review Concepts
Display types: Page, Block, Feed, Attachment, REST Export
Contextual filters: receive argument from URL or a default value
"Provide default value" options: raw value, node ID, taxonomy term, PHP code
Validation options and "Action to take if filter value does not validate"
Relationships must be added before you can use related fields as contextual filters
Relationships: joins between entity types (e.g. node → taxonomy term → other content referencing that term)
Exposed filters vs contextual filters: know the difference
Views caching: time-based vs tag-based
Rendering a view programmatically: views_embed_view('view_name', 'display_id')
Sub-theme from a Base Theme
Review Concepts
base theme key in mytheme.info.yml
Inheritance: sub-theme inherits templates, libraries, and regions from base theme
Overriding: copy template from base theme into sub-theme to override
libraries-extend to add to a base theme library without replacing it
Common base themes: Drupal 11+: Gin Admin (based on Claro)
Starterkit workflow: php core/scripts/drupal generate-theme command
Layout Builder
Review Concepts
Core module (enable via Extend)
Two modes: layouts for content types (templated) vs individual overrides per node
Sections: a row with a chosen layout (one column, two column, etc.)
Blocks are placed inside sections
Layout Builder vs Panels vs Display Suite — know Layout Builder is the current core approach
Inline blocks: only exist within the Layout Builder context
Reusable blocks: shared across Layout Builder layouts
Security
Review Concepts
Text formats and risk of "Full HTML" given to wrong roles
Input filtering: which tags are allowed per format
File upload security: allowed extensions, file size limits
Role permissions — principle of least privilege
administer permissions as elevated risk
CSRF protection in forms (built into Form API)
Security advisories and the importance of keeping core/modules updated
Auto-escaping in Twig: output is escaped by default (feature, not a bug)
|raw filter bypasses escaping (dangerous if applied to user input)
{{ content.field_name }} is safe
{{ node.field_name.value|raw }} is risky
Xss::filter() and Html::escape() in preprocess functions
Never trust $_GET, $_POST, or route parameters without sanitization in .theme files
CSS injection via user-controlled class names (|clean_class filter)
Performance
Review Concepts
CSS/JS aggregation (Admin → Configuration → Performance)
Page caching and dynamic page cache modules
Cache tags, contexts, and max-age — the three axes of Drupal caching
Views caching settings (time vs tag-based)
Image optimization: image styles, lazy loading
CDN integration at the config level
Unnecessary library loading — attaching libraries globally vs only where needed
Render caching: #cache properties on render arrays
Avoiding uncached output in Twig ( {{ 'now'|date }} style antipatterns)
Image dimension attributes to prevent layout shift (CLS)
Deferring non-critical JS (preprocess: false pitfalls)
Heavy preprocess functions that run expensive queries on every page load