SlideShare a Scribd company logo
Drupal 8
Theme System
The Backend of Frontend
Scott Reeves (Cottser)
Scott Reeves - @Cottser
Team Lead at Digital Echidna
Drupal 8 theme system
and Stable co-maintainer
Drupal 8 provisional core committer
Drupal 8
theme layer
changes
Theme functions
are gone!
Libraries
Template process layer
is gone!
Theme suggestion hooks
Drupal 7:
/**
* Implements hook_preprocess_HOOK() for node templates.
*/
function MYTHEME_preprocess_node(&$variables) {
$variables['theme_hook_suggestions'][] = 'node__' . 'my_first_suggestion';
$variables['theme_hook_suggestions'][] = 'node__' . 'my_second_more_specific_suggestion'
}
Drupal 8:
/**
* Implements hook_theme_suggestions_HOOK_alter() for node templates.
*/
function MYTHEME_theme_suggestions_node_alter(array &$suggestions, array $variables) {
$suggestions[] = 'node__' . 'my_first_suggestion';
$suggestions[] = 'node__' . 'my_second_suggestion';
}
Goodbye theme(), hello
render arrays
Drupal 7:
$variables['list'] = theme('item_list', array(
'items' => $items,
));
Drupal 8:
$variables['list'] = [
'#theme' => 'item_list',
'#items' => $items,
];
Attributes
All the HTML attributes:
<div{{ attributes }}>
Please don't do this, you will end up with yucky whitespace:
<div✖{{ attributes }}>
More attributes
Class manipulation:
<div{{ attributes.addClass('hello').removeClass('goodbye') }}>
Testing:
{% if attributes.hasClass('field-label-inline') %}
{# Do something special here. #}
{% endif %}
Even more attributes
Set attribute:
<div{{ attributes.setAttribute('id', 'eye-d') }}>
Remove attribute:
<div{{ attributes.removeAttribute('id') }}>
Print what you want,
when you want
Drupal 7: Drupal 8:
// We hide the comments and links
// to print them later.
hide($content['comments']);
hide($content['links']);
print render($content);
// Render calls show() on the element.
print render($content['links']);
// To get back links with the content.
show($content['links']);
// Prints content with links yet
// without comments :(
print render($content);
{# Print without comments and links #}
{{ content|without('comments', 'links') }}
{# Print only links #}
{{ content.links }}
{# Print everything without comment! #}
{{ content|without('comments') }}
{# Print everything #}
{{ content }}
Oh yeah, and Twig!
services.yml:
parameters:
twig.config:
debug: true
Example output:
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'block' -->
<!-- FILE NAME SUGGESTIONS:
* block--bartik-powered.html.twig
* block--system-powered-by-block.html.twig
* block--system.html.twig
x block.html.twig
-->
<!-- BEGIN OUTPUT from 'core/themes/bartik/templates/block.html.twig' -->
<div id="block-bartik-powered" role="complementary" class="block block-system block-system-powered-by-bloc
<div class="content">
<span>Powered by <a href="http://drupal.org">Drupal</a></span>
</div>
</div>
<!-- END OUTPUT from 'core/themes/bartik/templates/block.html.twig' -->
Drupal 7.33+
settings.php:
$conf['theme_debug'] = TRUE;
Example output:
<!-- THEME DEBUG -->
<!-- CALL: theme('block') -->
<!-- FILE NAME SUGGESTIONS:
* block--system--powered-by.tpl.php
* block--system.tpl.php
* block--footer.tpl.php
x block.tpl.php
-->
<!-- BEGIN OUTPUT from 'modules/block/block.tpl.php' -->
<div id="block-system-powered-by" class="block block-system">
<div class="content">
<span>Powered by <a href="https://www.drupal.org">Drupal</a></span>
</div>
</div>
<!-- END OUTPUT from 'modules/block/block.tpl.php' -->
Sandwiches.
https://github.com/DrupalTwig/sandwich
De ne with hook_theme()
/**
* Implements hook_theme().
*/
function sandwich_theme() {
return [
'sandwich' => [
'variables' => [
'attributes' => [],
'name' => '',
'bread' => '',
'cheese' => '',
'veggies' => [],
'protein' => '',
'condiments' => [],
],
],
];
}
Build your render array data
/**
* Builds a sandwich.
*/
public function build() {
return [
'#theme' => 'sandwich',
'#name' => $this->t('Chickado'),
'#attributes' => [
'id' => 'best-sandwich',
'style' => 'float: left;',
'class' => ['left', 'clearfix'],
],
'#bread' => $this->t('Sourdough'),
'#cheese' => $this->t('Gruyère'),
'#veggies' => [$this->t('Avocado'), $this->t('Red onion'), $this->t('Romaine')],
'#protein' => $this->t('Chicken'),
'#condiments' => [$this->t('Mayo'), $this->t('Dijon')],
];
}
Pass in variables using #-pre xed keys.
Markup your Twig template
<section{{ attributes }}>
<h2>{{ name }}</h2>
{% if bread %}
<p><strong>Bread:</strong> {{ bread }}</p>
{% endif %}
{% if protein %}
<p><strong>Protein:</strong> {{ protein }}</p>
{% endif %}
{% if cheese %}
<p><strong>Cheese:</strong> {{ cheese }}</p>
{% endif %}
{% if veggies %}
<strong>Veggies:</strong>
<ul>
{% for veg in veggies %}
<li>{{ veg }}</li>
{% endfor %}
Voilà!
Overview of Drupal 7
rendering ow
1. drupal_render()
2. #pre_render
3. theme()
4. Preprocess functions (and suggestions)
5. Template/theme function is rendered
7. #post_render
Overview of Drupal 8
rendering ow
1. Drupal::service('renderer')->render()
2. #pre_render
3. Drupal::theme()->render()
4. Theme suggestion hooks
5. Preprocess functions
6. Template is rendered
7. #post_render
Twig magic
{{ sandwich.cheese }}
// Array key.
$sandwich['cheese'];
// Object property.
$sandwich->cheese;
// Also works for magic get (provided you implement magic isset).
$sandwich->__isset('cheese'); && $sandwich->__get('cheese');
// Object method.
$sandwich->cheese();
// Object get method convention.
$sandwich->getCheese();
// Object is method convention.
$sandwich->isCheese();
// Method doesn't exist/dynamic method.
$sandwich->__call('cheese');
Autoescape
$user->field_first_name = "<script>alert('XSS')</script>";
Drupal 7:
Drupal 8:
BAD <?php print $user->field_first_name; ?>
GOOD <?php print check_plain($user->field_first_name); ?>
GOOD {{ user.field_first_name }}
BAD {{ user.field_first_name|raw }}
Thanks!
Questions?

More Related Content

What's hot (20)

PPTX
Dc kyiv2010 jun_08
Andrii Podanenko
 
PDF
Brisbane Drupal meetup - 2016 Mar - Build module in Drupal 8
Vladimir Roudakov
 
PDF
Drupal 8 版型開發變革
Chris Wu
 
PDF
Sergei Stryukov.Drush.Why it should be used.DrupalCamp Kyiv 2011
camp_drupal_ua
 
PPT
Multi Tenancy With Python and Django
scottcrespo
 
PPTX
8 things to know about theming in drupal 8
Logan Farr
 
PDF
Best Practice Site Architecture in Drupal 8
Pantheon
 
PDF
Introduction to Drupal - Installation, Anatomy, Terminologies
Gerald Villorente
 
PDF
Building a theming system with React - Matteo Ronchi - Codemotion Amsterdam 2017
Codemotion
 
PDF
Drush - use full power - DrupalCamp Donetsk 2014
Alex S
 
PPTX
WordCamp Ann Arbor 2015 Introduction to Backbone + WP REST API
Brian Hogg
 
PDF
mapserver_install_linux
tutorialsruby
 
PPTX
Becoming A Drupal Master Builder
Philip Norton
 
PDF
A WordPress workshop at Cefalo
Beroza Paul
 
PPTX
Converting (X)HTML/CSS template to Drupal 7 Theme
Adolfo Nasol
 
PPTX
Mojo – Simple REST Server
hendrikvb
 
PDF
Building a Custom Theme in Drupal 8
Anne Tomasevich
 
PDF
Getting to The Loop - London Wordpress Meetup July 28th
Chris Adams
 
PDF
Getting Started with Couchbase Ruby
Sergey Avseyev
 
PDF
Configuration Management in Drupal 8: A preview (DrupalCamp Alpe Adria 2014)
Nuvole
 
Dc kyiv2010 jun_08
Andrii Podanenko
 
Brisbane Drupal meetup - 2016 Mar - Build module in Drupal 8
Vladimir Roudakov
 
Drupal 8 版型開發變革
Chris Wu
 
Sergei Stryukov.Drush.Why it should be used.DrupalCamp Kyiv 2011
camp_drupal_ua
 
Multi Tenancy With Python and Django
scottcrespo
 
8 things to know about theming in drupal 8
Logan Farr
 
Best Practice Site Architecture in Drupal 8
Pantheon
 
Introduction to Drupal - Installation, Anatomy, Terminologies
Gerald Villorente
 
Building a theming system with React - Matteo Ronchi - Codemotion Amsterdam 2017
Codemotion
 
Drush - use full power - DrupalCamp Donetsk 2014
Alex S
 
WordCamp Ann Arbor 2015 Introduction to Backbone + WP REST API
Brian Hogg
 
mapserver_install_linux
tutorialsruby
 
Becoming A Drupal Master Builder
Philip Norton
 
A WordPress workshop at Cefalo
Beroza Paul
 
Converting (X)HTML/CSS template to Drupal 7 Theme
Adolfo Nasol
 
Mojo – Simple REST Server
hendrikvb
 
Building a Custom Theme in Drupal 8
Anne Tomasevich
 
Getting to The Loop - London Wordpress Meetup July 28th
Chris Adams
 
Getting Started with Couchbase Ruby
Sergey Avseyev
 
Configuration Management in Drupal 8: A preview (DrupalCamp Alpe Adria 2014)
Nuvole
 

Similar to Drupal 8 Theme System: The Backend of Frontend (20)

PDF
Atomicant Drupal 6 Theming
Marek Sotak
 
PDF
The Flexibility of Drupal 8 | DCNLights 2017
Michael Miles
 
PDF
Drupal theming - a practical approach (European Drupal Days 2015)
Eugenio Minardi
 
PDF
Drupal 8: frontend development
sparkfabrik
 
PDF
Drupal 8 theming deep dive
Romain Jarraud
 
PDF
Drupal Render API
Pavel Makhrinsky
 
PDF
Drupal 7 Theming - Behind the scenes
ramakesavan
 
PPT
Render API - Pavel Makhrinsky
DrupalCampDN
 
ODP
Drupal Theme Development - DrupalCon Chicago 2011
Ryan Price
 
PDF
Drupal8 themingdeepdive drupaldevdays-montpellier17042015
Romain Jarraud
 
PDF
Introduction to Drupal (7) Theming
Robert Carr
 
PPTX
Drupal theming
Arshad Vayani
 
PDF
The Flexibility of Drupal 8
Michael Miles
 
PDF
Designing with Drupal 8
Snake Hill Web Agency
 
PDF
D7 theming what's new - London
Marek Sotak
 
PPTX
Drupal Camp Porto - Developing with Drupal: First Steps
Luís Carneiro
 
ODP
DrupalEasy: Intro to Theme Development
ultimike
 
PDF
Learning PHP for Drupal Theming, DC Chicago 2009
Emma Jane Hogbin Westby
 
PDF
Drupal 8: Theming
drubb
 
PDF
Twig in drupal8
Wizzlern
 
Atomicant Drupal 6 Theming
Marek Sotak
 
The Flexibility of Drupal 8 | DCNLights 2017
Michael Miles
 
Drupal theming - a practical approach (European Drupal Days 2015)
Eugenio Minardi
 
Drupal 8: frontend development
sparkfabrik
 
Drupal 8 theming deep dive
Romain Jarraud
 
Drupal Render API
Pavel Makhrinsky
 
Drupal 7 Theming - Behind the scenes
ramakesavan
 
Render API - Pavel Makhrinsky
DrupalCampDN
 
Drupal Theme Development - DrupalCon Chicago 2011
Ryan Price
 
Drupal8 themingdeepdive drupaldevdays-montpellier17042015
Romain Jarraud
 
Introduction to Drupal (7) Theming
Robert Carr
 
Drupal theming
Arshad Vayani
 
The Flexibility of Drupal 8
Michael Miles
 
Designing with Drupal 8
Snake Hill Web Agency
 
D7 theming what's new - London
Marek Sotak
 
Drupal Camp Porto - Developing with Drupal: First Steps
Luís Carneiro
 
DrupalEasy: Intro to Theme Development
ultimike
 
Learning PHP for Drupal Theming, DC Chicago 2009
Emma Jane Hogbin Westby
 
Drupal 8: Theming
drubb
 
Twig in drupal8
Wizzlern
 
Ad

More from Acquia (20)

PDF
Acquia_Adcetera Webinar_Marketing Automation.pdf
Acquia
 
PDF
Acquia Webinar Deck - 9_13 .pdf
Acquia
 
PDF
Taking Your Multi-Site Management at Scale to the Next Level
Acquia
 
PDF
CDP for Retail Webinar with Appnovation - Q2 2022.pdf
Acquia
 
PDF
May Partner Bootcamp 2022
Acquia
 
PDF
April Partner Bootcamp 2022
Acquia
 
PDF
How to Unify Brand Experience: A Hootsuite Story
Acquia
 
PDF
Using Personas to Guide DAM Results: How Life Time Pumped Up Their UX and CX
Acquia
 
PDF
Improve Code Quality and Time to Market: 100% Cloud-Based Development Workflow
Acquia
 
PDF
September Partner Bootcamp
Acquia
 
PDF
August partner bootcamp
Acquia
 
PDF
July 2021 Partner Bootcamp
Acquia
 
PDF
May Partner Bootcamp
Acquia
 
PDF
DRUPAL 7 END OF LIFE IS NEAR - MIGRATE TO DRUPAL 9 FAST AND EASY
Acquia
 
PDF
Work While You Sleep: The CMO’s Guide to a 24/7/365 Lead Machine
Acquia
 
PDF
Acquia webinar: Leveraging Drupal to Bury Your Sales Team In B2B Leads
Acquia
 
PDF
April partner bootcamp deck cookieless future
Acquia
 
PDF
How to enhance cx through personalised, automated solutions
Acquia
 
PDF
DRUPAL MIGRATIONS AND DRUPAL 9 INNOVATION: HOW PAC-12 DELIVERED DIGITALLY FOR...
Acquia
 
PDF
Customer Experience (CX): 3 Key Factors Shaping CX Redesign in 2021
Acquia
 
Acquia_Adcetera Webinar_Marketing Automation.pdf
Acquia
 
Acquia Webinar Deck - 9_13 .pdf
Acquia
 
Taking Your Multi-Site Management at Scale to the Next Level
Acquia
 
CDP for Retail Webinar with Appnovation - Q2 2022.pdf
Acquia
 
May Partner Bootcamp 2022
Acquia
 
April Partner Bootcamp 2022
Acquia
 
How to Unify Brand Experience: A Hootsuite Story
Acquia
 
Using Personas to Guide DAM Results: How Life Time Pumped Up Their UX and CX
Acquia
 
Improve Code Quality and Time to Market: 100% Cloud-Based Development Workflow
Acquia
 
September Partner Bootcamp
Acquia
 
August partner bootcamp
Acquia
 
July 2021 Partner Bootcamp
Acquia
 
May Partner Bootcamp
Acquia
 
DRUPAL 7 END OF LIFE IS NEAR - MIGRATE TO DRUPAL 9 FAST AND EASY
Acquia
 
Work While You Sleep: The CMO’s Guide to a 24/7/365 Lead Machine
Acquia
 
Acquia webinar: Leveraging Drupal to Bury Your Sales Team In B2B Leads
Acquia
 
April partner bootcamp deck cookieless future
Acquia
 
How to enhance cx through personalised, automated solutions
Acquia
 
DRUPAL MIGRATIONS AND DRUPAL 9 INNOVATION: HOW PAC-12 DELIVERED DIGITALLY FOR...
Acquia
 
Customer Experience (CX): 3 Key Factors Shaping CX Redesign in 2021
Acquia
 
Ad

Recently uploaded (20)

PDF
UPDF - AI PDF Editor & Converter Key Features
DealFuel
 
PDF
SIZING YOUR AIR CONDITIONER---A PRACTICAL GUIDE.pdf
Muhammad Rizwan Akram
 
PDF
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
PPTX
Agentforce World Tour Toronto '25 - MCP with MuleSoft
Alexandra N. Martinez
 
PDF
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
DOCX
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
DOCX
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
PDF
Transcript: Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
PPTX
Designing_the_Future_AI_Driven_Product_Experiences_Across_Devices.pptx
presentifyai
 
PDF
The 2025 InfraRed Report - Redpoint Ventures
Razin Mustafiz
 
PDF
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
PDF
Automating Feature Enrichment and Station Creation in Natural Gas Utility Net...
Safe Software
 
PDF
“Squinting Vision Pipelines: Detecting and Correcting Errors in Vision Models...
Edge AI and Vision Alliance
 
PDF
Future-Proof or Fall Behind? 10 Tech Trends You Can’t Afford to Ignore in 2025
DIGITALCONFEX
 
PDF
The Rise of AI and IoT in Mobile App Tech.pdf
IMG Global Infotech
 
PDF
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
PDF
LOOPS in C Programming Language - Technology
RishabhDwivedi43
 
PPT
Ericsson LTE presentation SEMINAR 2010.ppt
npat3
 
PDF
AI Agents in the Cloud: The Rise of Agentic Cloud Architecture
Lilly Gracia
 
PPTX
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 
UPDF - AI PDF Editor & Converter Key Features
DealFuel
 
SIZING YOUR AIR CONDITIONER---A PRACTICAL GUIDE.pdf
Muhammad Rizwan Akram
 
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
Agentforce World Tour Toronto '25 - MCP with MuleSoft
Alexandra N. Martinez
 
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
Transcript: Book industry state of the nation 2025 - Tech Forum 2025
BookNet Canada
 
Designing_the_Future_AI_Driven_Product_Experiences_Across_Devices.pptx
presentifyai
 
The 2025 InfraRed Report - Redpoint Ventures
Razin Mustafiz
 
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
Automating Feature Enrichment and Station Creation in Natural Gas Utility Net...
Safe Software
 
“Squinting Vision Pipelines: Detecting and Correcting Errors in Vision Models...
Edge AI and Vision Alliance
 
Future-Proof or Fall Behind? 10 Tech Trends You Can’t Afford to Ignore in 2025
DIGITALCONFEX
 
The Rise of AI and IoT in Mobile App Tech.pdf
IMG Global Infotech
 
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
LOOPS in C Programming Language - Technology
RishabhDwivedi43
 
Ericsson LTE presentation SEMINAR 2010.ppt
npat3
 
AI Agents in the Cloud: The Rise of Agentic Cloud Architecture
Lilly Gracia
 
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 

Drupal 8 Theme System: The Backend of Frontend

  • 1. Drupal 8 Theme System The Backend of Frontend Scott Reeves (Cottser)
  • 2. Scott Reeves - @Cottser Team Lead at Digital Echidna Drupal 8 theme system and Stable co-maintainer Drupal 8 provisional core committer
  • 7. Theme suggestion hooks Drupal 7: /** * Implements hook_preprocess_HOOK() for node templates. */ function MYTHEME_preprocess_node(&$variables) { $variables['theme_hook_suggestions'][] = 'node__' . 'my_first_suggestion'; $variables['theme_hook_suggestions'][] = 'node__' . 'my_second_more_specific_suggestion' } Drupal 8: /** * Implements hook_theme_suggestions_HOOK_alter() for node templates. */ function MYTHEME_theme_suggestions_node_alter(array &$suggestions, array $variables) { $suggestions[] = 'node__' . 'my_first_suggestion'; $suggestions[] = 'node__' . 'my_second_suggestion'; }
  • 8. Goodbye theme(), hello render arrays Drupal 7: $variables['list'] = theme('item_list', array( 'items' => $items, )); Drupal 8: $variables['list'] = [ '#theme' => 'item_list', '#items' => $items, ];
  • 9. Attributes All the HTML attributes: <div{{ attributes }}> Please don't do this, you will end up with yucky whitespace: <div✖{{ attributes }}>
  • 10. More attributes Class manipulation: <div{{ attributes.addClass('hello').removeClass('goodbye') }}> Testing: {% if attributes.hasClass('field-label-inline') %} {# Do something special here. #} {% endif %}
  • 11. Even more attributes Set attribute: <div{{ attributes.setAttribute('id', 'eye-d') }}> Remove attribute: <div{{ attributes.removeAttribute('id') }}>
  • 12. Print what you want, when you want Drupal 7: Drupal 8: // We hide the comments and links // to print them later. hide($content['comments']); hide($content['links']); print render($content); // Render calls show() on the element. print render($content['links']); // To get back links with the content. show($content['links']); // Prints content with links yet // without comments :( print render($content); {# Print without comments and links #} {{ content|without('comments', 'links') }} {# Print only links #} {{ content.links }} {# Print everything without comment! #} {{ content|without('comments') }} {# Print everything #} {{ content }}
  • 13. Oh yeah, and Twig!
  • 14. services.yml: parameters: twig.config: debug: true Example output: <!-- THEME DEBUG --> <!-- THEME HOOK: 'block' --> <!-- FILE NAME SUGGESTIONS: * block--bartik-powered.html.twig * block--system-powered-by-block.html.twig * block--system.html.twig x block.html.twig --> <!-- BEGIN OUTPUT from 'core/themes/bartik/templates/block.html.twig' --> <div id="block-bartik-powered" role="complementary" class="block block-system block-system-powered-by-bloc <div class="content"> <span>Powered by <a href="http://drupal.org">Drupal</a></span> </div> </div> <!-- END OUTPUT from 'core/themes/bartik/templates/block.html.twig' -->
  • 15. Drupal 7.33+ settings.php: $conf['theme_debug'] = TRUE; Example output: <!-- THEME DEBUG --> <!-- CALL: theme('block') --> <!-- FILE NAME SUGGESTIONS: * block--system--powered-by.tpl.php * block--system.tpl.php * block--footer.tpl.php x block.tpl.php --> <!-- BEGIN OUTPUT from 'modules/block/block.tpl.php' --> <div id="block-system-powered-by" class="block block-system"> <div class="content"> <span>Powered by <a href="https://www.drupal.org">Drupal</a></span> </div> </div> <!-- END OUTPUT from 'modules/block/block.tpl.php' -->
  • 17. De ne with hook_theme() /** * Implements hook_theme(). */ function sandwich_theme() { return [ 'sandwich' => [ 'variables' => [ 'attributes' => [], 'name' => '', 'bread' => '', 'cheese' => '', 'veggies' => [], 'protein' => '', 'condiments' => [], ], ], ]; }
  • 18. Build your render array data /** * Builds a sandwich. */ public function build() { return [ '#theme' => 'sandwich', '#name' => $this->t('Chickado'), '#attributes' => [ 'id' => 'best-sandwich', 'style' => 'float: left;', 'class' => ['left', 'clearfix'], ], '#bread' => $this->t('Sourdough'), '#cheese' => $this->t('Gruyère'), '#veggies' => [$this->t('Avocado'), $this->t('Red onion'), $this->t('Romaine')], '#protein' => $this->t('Chicken'), '#condiments' => [$this->t('Mayo'), $this->t('Dijon')], ]; } Pass in variables using #-pre xed keys.
  • 19. Markup your Twig template <section{{ attributes }}> <h2>{{ name }}</h2> {% if bread %} <p><strong>Bread:</strong> {{ bread }}</p> {% endif %} {% if protein %} <p><strong>Protein:</strong> {{ protein }}</p> {% endif %} {% if cheese %} <p><strong>Cheese:</strong> {{ cheese }}</p> {% endif %} {% if veggies %} <strong>Veggies:</strong> <ul> {% for veg in veggies %} <li>{{ veg }}</li> {% endfor %}
  • 21. Overview of Drupal 7 rendering ow 1. drupal_render() 2. #pre_render 3. theme() 4. Preprocess functions (and suggestions) 5. Template/theme function is rendered 7. #post_render
  • 22. Overview of Drupal 8 rendering ow 1. Drupal::service('renderer')->render() 2. #pre_render 3. Drupal::theme()->render() 4. Theme suggestion hooks 5. Preprocess functions 6. Template is rendered 7. #post_render
  • 23. Twig magic {{ sandwich.cheese }} // Array key. $sandwich['cheese']; // Object property. $sandwich->cheese; // Also works for magic get (provided you implement magic isset). $sandwich->__isset('cheese'); && $sandwich->__get('cheese'); // Object method. $sandwich->cheese(); // Object get method convention. $sandwich->getCheese(); // Object is method convention. $sandwich->isCheese(); // Method doesn't exist/dynamic method. $sandwich->__call('cheese');
  • 24. Autoescape $user->field_first_name = "<script>alert('XSS')</script>"; Drupal 7: Drupal 8: BAD <?php print $user->field_first_name; ?> GOOD <?php print check_plain($user->field_first_name); ?> GOOD {{ user.field_first_name }} BAD {{ user.field_first_name|raw }}