@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
mytheme.themephp
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
custom.jsjavascript
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 themekey inmytheme.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-extendto 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 filterbypasses escaping (dangerous if applied to user input){{ content.field_name }}is safe{{ node.field_name.value|raw }}is riskyXss::filter() and Html::escape()in preprocess functions- Never trust
$_GET,$_POST, or route parameters without sanitization in.themefiles - CSS injection via user-controlled class names (
|clean_classfilter)
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