Aha! Understanding and Using Render Arrays in Drupal 8 Gus - - PowerPoint PPT Presentation

aha understanding and using render arrays in drupal 8 gus
SMART_READER_LITE
LIVE PREVIEW

Aha! Understanding and Using Render Arrays in Drupal 8 Gus - - PowerPoint PPT Presentation

Aha! Understanding and Using Render Arrays in Drupal 8 Gus Childs @guschilds chromatichq.com @chromatichq lets talk about render arrays but why render arrays? problem: build feature X like the last site but slightly different


slide-1
SLIDE 1

Aha! Understanding and Using Render Arrays in Drupal 8

slide-2
SLIDE 2

Gus Childs

@guschilds

slide-3
SLIDE 3

chromatichq.com @chromatichq

slide-4
SLIDE 4
slide-5
SLIDE 5
slide-6
SLIDE 6

let’s talk about render arrays

slide-7
SLIDE 7

but why render arrays?

slide-8
SLIDE 8

problem: build feature X like the last site but slightly different

slide-9
SLIDE 9

solution: copy/paste?

slide-10
SLIDE 10

Don’t Repeat Yourself!

slide-11
SLIDE 11

solution: abstraction

slide-12
SLIDE 12

render arrays are abstract

(picturesbyann, Flickr)

slide-13
SLIDE 13

(davidchief, Flickr)

slide-14
SLIDE 14

“arrays in Drupal 8?!” -you

slide-15
SLIDE 15
slide-16
SLIDE 16

“yeah, sorry.” -maintainers

slide-17
SLIDE 17

Aha! Understanding and Using Render Arrays in Drupal 8

slide-18
SLIDE 18

Render Arrays:

what they look like how they work why they’re useful the Render API their future

slide-19
SLIDE 19

what do render arrays look like?

(Pulp Fiction)

slide-20
SLIDE 20

theme() render arrays

slide-21
SLIDE 21

// Using theme() in D7. $logo = theme('image', array( 'path' => 'logo.png', 'alt' => t('My logo!'), ));

slide-22
SLIDE 22

// Using theme() in D7. $logo = theme('image', array( 'path' => 'logo.png', 'alt' => t('My logo!'), ));

slide-23
SLIDE 23

// Using theme() in D7. $logo = theme('image', array( 'path' => 'logo.png', 'alt' => t('My logo!'), ));

slide-24
SLIDE 24

// The equivalent render array in D7. $logo = array( '#theme' => 'image', '#path' => 'logo.png', '#alt' => t('My logo!'), );

slide-25
SLIDE 25

// The equivalent render array in D7. $logo = array( '#theme' => 'image', '#path' => 'logo.png', '#alt' => t('My logo!'), );

slide-26
SLIDE 26

// The equivalent render array in D7. $logo = array( '#theme' => 'image', '#path' => 'logo.png', '#alt' => t('My logo!'), );

slide-27
SLIDE 27

// The equivalent render array in D7. $logo = array( '#theme' => 'image', '#path' => 'logo.png', '#alt' => t('My logo!'), );

slide-28
SLIDE 28

// Using theme() in D7. $logo = theme('image', array( 'path' => 'logo.png', 'alt' => t('My logo!'), ));

slide-29
SLIDE 29

// Printing a string variable in D7. <?php print $logo; ?>

slide-30
SLIDE 30

// The resulting markup. <img src="logo.png" alt="My logo!" />

slide-31
SLIDE 31

// The equivalent render array in D7. $logo = array( '#theme' => 'image', '#path' => 'logo.png', '#alt' => t('My logo!'), );

slide-32
SLIDE 32

// How to NOT print a render array in D7. <?php print $logo; ?>

slide-33
SLIDE 33

// The result. Huh? Array

slide-34
SLIDE 34

// Rendering/printing a render array in D7. <?php print render($logo); ?>

slide-35
SLIDE 35

// The resulting markup. That’s better. <img src="logo.png" alt="My logo!" />

slide-36
SLIDE 36

// Printing/rendering anything in D8. {{ logo }}

slide-37
SLIDE 37

// Printing/rendering a render array in D7. <?php print render($logo); ?> // Printing/rendering a render array in D8. {{ logo }}

slide-38
SLIDE 38

// A simplified page array. array( 'header' => array(...), 'content' => array( 'node' => array( '#theme' => 'node', '#node' => Object, '#view_mode' => 'full', ), ), 'sidebar_first' => array(...), 'footer' => array(...), );

slide-39
SLIDE 39

// Rendering the content region in D7. <?php print render($page['content']); ?>

drupal7/modules/system/page.tpl.php

slide-40
SLIDE 40

// Rendering the content region in D8. {{ page.content }}

drupal8/core/themes/stable/templates/layout/page.html.twig

slide-41
SLIDE 41

// A simplified page array. array( 'header' => array(...), 'content' => array( 'node' => array( '#theme' => 'node', '#node' => Object, '#view_mode' => 'full', ), ), 'sidebar_first' => array(...), 'footer' => array(...), );

slide-42
SLIDE 42

// A simplified page array. array( 'header' => array(...), 'content' => array( 'node' => array( '#theme' => 'node', '#node' => Object, '#view_mode' => 'full', ), ), 'sidebar_first' => array(...), 'footer' => array(...), );

slide-43
SLIDE 43

how do render arrays work?

(Pete Birkinshaw, Flickr)

slide-44
SLIDE 44

// Printing/rendering a render array in D7. <?php print render($logo); ?> // Printing/rendering a render array in D8. {{ logo }}

slide-45
SLIDE 45

// Our simple render array in D7. $logo = array( '#theme' => 'image', '#path' => 'logo.png', '#alt' => t('My logo!'), );

slide-46
SLIDE 46

// The resulting markup. <img src="logo.png" alt="My logo!" />

slide-47
SLIDE 47

Theme System

(Erin Khoo, Flickr)

slide-48
SLIDE 48

/** * Implements hook_theme(). */ function system_theme() { return array( 'html' => array( 'render element' => 'html', 'template' => 'html', ), 'page' => array( 'render element' => 'page', 'template' => 'page', ), // (Other theme hook definitions). ); }

drupal7/modules/system/system.module drupal7/includes/theme.inc (simplified)

slide-49
SLIDE 49

/** * Implements hook_theme(). */ function system_theme() { return array( 'html' => array( 'render element' => 'html', ), 'page' => array( 'render element' => 'page', ), // (Other theme hook definitions). ); }

drupal8/core/modules/system/system.module drupal8/core/includes/theme.inc (simplified)

slide-50
SLIDE 50

/** * Implements hook_theme(). */ function system_theme() { return array( 'image' => array( 'variables' => array( 'path' => NULL, 'width' => NULL, 'height' => NULL, 'alt' => '', 'title' => NULL, 'attributes' => array(), ), ), ); }

drupal7/modules/system/system.module drupal7/includes/theme.inc (simplified)

slide-51
SLIDE 51

/** * Implements hook_theme(). */ function system_theme() { return array( 'image' => array( 'variables' => array( 'path' => NULL, 'width' => NULL, 'height' => NULL, 'alt' => '', 'title' => NULL, 'attributes' => array(), ), ), ); }

drupal7/modules/system/system.module drupal7/includes/theme.inc (simplified)

slide-52
SLIDE 52

/** * Implements hook_theme(). */ function system_theme() { return array( 'image' => array( 'variables' => array( 'path' => NULL, 'width' => NULL, 'height' => NULL, 'alt' => '', 'title' => NULL, 'attributes' => array(), ), ), ); }

drupal7/modules/system/system.module drupal7/includes/theme.inc (simplified)

slide-53
SLIDE 53

// Our simple render array in D7. $logo = array( '#theme' => 'image', '#path' => 'logo.png', '#alt' => t('My logo!'), );

slide-54
SLIDE 54

// Our simple render array in D7. $logo = array( '#theme' => 'image', '#path' => 'logo.png', '#alt' => t('My logo!'), );

slide-55
SLIDE 55

// Our simple render array in D7. $logo = array( '#theme' => 'image', '#path' => 'logo.png', '#alt' => t('My logo!'), );

slide-56
SLIDE 56

/** * Implements hook_theme(). */ function system_theme() { return array( 'image' => array( 'variables' => array( 'path' => NULL, 'width' => NULL, 'height' => NULL, 'alt' => '', 'title' => NULL, 'attributes' => array(), ), ), ); }

drupal7/modules/system/system.module drupal7/includes/theme.inc (simplified)

slide-57
SLIDE 57

/** * Implements hook_theme(). */ function system_theme() { return array( 'image' => array( 'variables' => array( 'path' => NULL, 'width' => NULL, 'height' => NULL, 'alt' => '', 'title' => NULL, 'attributes' => array(), ), ), ); }

drupal7/modules/system/system.module drupal7/includes/theme.inc (simplified)

slide-58
SLIDE 58

/** * Implements hook_theme(). */ function system_theme() { return array( 'image' => array( 'variables' => array( 'uri' => NULL, 'width' => NULL, 'height' => NULL, 'alt' => '', 'title' => NULL, 'attributes' => array(), 'sizes' => NULL, 'srcset' => array(), 'style_name' => NULL, ), ), ); }

drupal8/core/modules/system/system.module drupal8/core/includes/theme.inc (simplified)

slide-59
SLIDE 59

/** * Implements hook_theme(). */ function system_theme() { return array( 'image' => array( 'variables' => array( 'uri' => NULL, 'width' => NULL, 'height' => NULL, 'alt' => '', 'title' => NULL, 'attributes' => array(), 'sizes' => NULL, 'srcset' => array(), 'style_name' => NULL, ), ), ); }

drupal8/core/modules/system/system.module drupal8/core/includes/theme.inc (simplified)

slide-60
SLIDE 60

/** * Implements hook_theme(). */ function system_theme() { return array( 'image' => array( 'variables' => array( 'uri' => NULL, 'width' => NULL, 'height' => NULL, 'alt' => '', 'title' => NULL, 'attributes' => array(), 'sizes' => NULL, 'srcset' => array(), 'style_name' => NULL, ), ), ); }

drupal8/core/modules/system/system.module drupal8/core/includes/theme.inc (simplified)

slide-61
SLIDE 61

// Our simple render array in D7. $logo = array( '#theme' => 'image', '#path' => 'logo.png', '#alt' => t('My logo!'), );

slide-62
SLIDE 62

// Our simple render array in D8. $logo = array( '#theme' => 'image', '#uri' => 'public://logo.png', '#alt' => t('My logo!'), );

slide-63
SLIDE 63

// A responsive image render array in D8. $logo_uri = 'public://logo.png'; $logo = array( '#theme' => 'image', '#uri' => $logo_uri, '#alt' => t('My logo!'), '#sizes' => '100vw', '#srcset' => array( array( 'uri' => ImageStyle::load('thumbnail')->buildUri($logo_uri), 'width' => '250w', ), array( 'uri' => ImageStyle::load('large')->buildUri($logo_uri), 'width' => '750w', ), ), );

slide-64
SLIDE 64

// A responsive image render array in D8. $logo_uri = 'public://logo.png'; $logo = array( '#theme' => 'image', '#uri' => $logo_uri, '#alt' => t('My logo!'), '#sizes' => '100vw', '#srcset' => array( array( 'uri' => ImageStyle::load('thumbnail')->buildUri($logo_uri), 'width' => '250w', ), array( 'uri' => ImageStyle::load('large')->buildUri($logo_uri), 'width' => '750w', ), ), );

slide-65
SLIDE 65

// A responsive image render array in D8. $logo_uri = 'public://logo.png'; $logo = array( '#theme' => 'image', '#uri' => $logo_uri, '#alt' => t('My logo!'), '#sizes' => '100vw', '#srcset' => array( array( 'uri' => ImageStyle::load('thumbnail')->buildUri($logo_uri), 'width' => '250w', ), array( 'uri' => ImageStyle::load('large')->buildUri($logo_uri), 'width' => '750w', ), ), );

slide-66
SLIDE 66

// A responsive image render array in D8. $logo_uri = 'public://logo.png'; $logo = array( '#theme' => 'image', '#uri' => $logo_uri, '#alt' => t('My logo!'), '#sizes' => '100vw', '#srcset' => array( array( 'uri' => ImageStyle::load('thumbnail')->buildUri($logo_uri), 'width' => '250w', ), array( 'uri' => ImageStyle::load('large')->buildUri($logo_uri), 'width' => '750w', ), ), );

slide-67
SLIDE 67

// The resulting responsive image markup. <img src="logo.png" alt="My logo!" sizes="100vw" srcset="styles/thumbnail/public/logo.png 250w, styles/large/public/logo.png 750w">

slide-68
SLIDE 68

// A responsive image render array in D8. $logo_uri = 'public://logo.png'; $logo = array( '#theme' => 'image', '#uri' => $logo_uri, '#alt' => t('My logo!'), '#sizes' => '100vw', '#srcset' => array( array( 'uri' => ImageStyle::load('thumbnail')->buildUri($logo_uri), 'width' => '250w', ), array( 'uri' => ImageStyle::load('large')->buildUri($logo_uri), 'width' => '750w', ), ), );

slide-69
SLIDE 69

// The resulting responsive image markup. <img src="logo.png" alt="My logo!" sizes="100vw" srcset="styles/thumbnail/public/logo.png 250w, styles/large/public/logo.png 750w">

slide-70
SLIDE 70

/** * Implements hook_theme(). */ function system_theme() { return array( 'html' => array( 'render element' => 'html', 'template' => 'html', ), 'page' => array( 'render element' => 'page', 'template' => 'page', ), 'image' => array( 'variables' => array( // Bunches 'o variables. ), ), ); }

drupal7/modules/system/system.module drupal7/includes/theme.inc (simplified)

slide-71
SLIDE 71

/** * Implements hook_theme(). */ function system_theme() { return array( 'html' => array( 'render element' => 'html', 'template' => 'html', ), 'page' => array( 'render element' => 'page', 'template' => 'page', ), 'image' => array( 'variables' => array( // Bunches 'o variables. ), ), ); }

drupal7/modules/system/system.module drupal7/includes/theme.inc (simplified)

slide-72
SLIDE 72

/** * Implements hook_theme(). */ function system_theme() { return array( 'html' => array( 'render element' => 'html', 'template' => 'html', ), 'page' => array( 'render element' => 'page', 'template' => 'page', ), 'image' => array( 'variables' => array( // Bunches 'o variables. ), ), ); }

drupal7/modules/system/system.module drupal7/includes/theme.inc (simplified)

slide-73
SLIDE 73

/** * Returns HTML for an image. */ function theme_image($variables) { $attributes = $variables['attributes']; $attributes['src'] = file_create_url($variables['path']); foreach (array('width', 'height', 'alt', 'title') as $key) { if (isset($variables[$key])) { $attributes[$key] = $variables[$key]; } } return '<img' . drupal_attributes($attributes) . ' />'; }

drupal7/includes/theme.inc

slide-74
SLIDE 74
slide-75
SLIDE 75

function theme_item_list($variables) { $items = $variables['items']; $title = $variables['title']; $type = $variables['type']; $attributes = $variables['attributes']; // Only output the list container and title, if there are any list items. // Check to see whether the block title exists before adding a header. // Empty headers are not semantic and present accessibility challenges. $output = '<div class="item-list">'; if (isset($title) && $title !== '') { $output .= '<h3>' . $title . '</h3>'; } if (!empty($items)) { $output .= "<$type" . drupal_attributes($attributes) . '>'; $num_items = count($items); $i = 0; foreach ($items as $item) { $attributes = array(); $children = array(); $data = ''; $i++; if (is_array($item)) { foreach ($item as $key => $value) { if ($key == 'data') { $data = $value; } elseif ($key == 'children') { $children = $value; } else { $attributes[$key] = $value; } } } else { $data = $item; } if (count($children) > 0) { // Render nested list. $data .= theme_item_list(array('items' => $children, 'title' => NULL, 'type' => $type, 'attributes' => $attributes)); } if ($i == 1) { $attributes['class'][] = 'first'; } if ($i == $num_items) { $attributes['class'][] = 'last'; } $output .= '<li' . drupal_attributes($attributes) . '>' . $data . "</li>\n"; } $output .= "</$type>"; } $output .= '</div>'; return $output; }

drupal7/includes/theme.inc

slide-76
SLIDE 76

Don’t Repeat Yourself!

slide-77
SLIDE 77

/** * Implements hook_theme(). */ function system_theme() { return array( 'html' => array( 'render element' => 'html', ), 'page' => array( 'render element' => 'page', ), ); }

drupal8/core/modules/system/system.module drupal8/core/includes/theme.inc (simplified)

slide-78
SLIDE 78

/** * Returns HTML for an image. */ function theme_image($variables) { $attributes = $variables['attributes']; $attributes['src'] = file_create_url($variables['path']); foreach (array('width', 'height', 'alt', 'title') as $key) { if (isset($variables[$key])) { $attributes[$key] = $variables[$key]; } } return '<img' . drupal_attributes($attributes) . ' />'; }

drupal7/includes/theme.inc

slide-79
SLIDE 79

drupal8/core/themes/stable/templates/field/image.html.twig

<img{{ attributes }} />

slide-80
SLIDE 80

drupal7/includes/theme.inc

/** * Returns HTML for an image. */ function theme_image($variables) { $attributes = $variables['attributes']; $attributes['src'] = file_create_url($variables['path']); foreach (array('width', 'height', 'alt', 'title') as $key) { if (isset($variables[$key])) { $attributes[$key] = $variables[$key]; } } return '<img' . drupal_attributes($attributes) . ' />'; }

slide-81
SLIDE 81

// A responsive image render array in D8. $logo_uri = 'public://logo.png'; $logo = array( '#theme' => 'image', '#uri' => $logo_uri, '#alt' => t('My logo!'), '#sizes' => '100vw', '#srcset' => array( array( 'uri' => ImageStyle::load('thumbnail')->buildUri($logo_uri), 'width' => '250w', ), array( 'uri' => ImageStyle::load('large')->buildUri($logo_uri), 'width' => '750w', ), ), );

slide-82
SLIDE 82

/** * Prepares variables for image templates. */ function template_preprocess_image(&$variables) { if (!empty($variables['uri'])) { $variables['attributes']['src'] = file_url_transform_relative(file_create_url($variables['uri'])); } // There is normally a lot of code here that takes the responsive variables // and turns them into properly formatted attribute values. foreach (array('width', 'height', 'alt', 'title', 'sizes') as $key) { if (isset($variables[$key])) { // If the property has already been defined in the attributes, // do not override, including NULL. if (array_key_exists($key, $variables['attributes'])) { continue; } $variables['attributes'][$key] = $variables[$key]; } } }

drupal8/core/includes/theme.inc

slide-83
SLIDE 83

/** * Prepares variables for image templates. */ function template_preprocess_image(&$variables) { if (!empty($variables['uri'])) { $variables['attributes']['src'] = file_url_transform_relative(file_create_url($variables['uri'])); } // There is normally a lot of code here that takes the responsive variables // and turns them into properly formatted attribute values. foreach (array('width', 'height', 'alt', 'title', 'sizes') as $key) { if (isset($variables[$key])) { // If the property has already been defined in the attributes, // do not override, including NULL. if (array_key_exists($key, $variables['attributes'])) { continue; } $variables['attributes'][$key] = $variables[$key]; } } }

drupal8/core/includes/theme.inc

slide-84
SLIDE 84

/** * Prepares variables for image templates. */ function template_preprocess_image(&$variables) { if (!empty($variables['uri'])) { $variables['attributes']['src'] = file_url_transform_relative(file_create_url($variables['uri'])); } // There is normally a lot of code here that takes the responsive variables // and turns them into properly formatted attribute values. foreach (array('width', 'height', 'alt', 'title', 'sizes') as $key) { if (isset($variables[$key])) { // If the property has already been defined in the attributes, // do not override, including NULL. if (array_key_exists($key, $variables['attributes'])) { continue; } $variables['attributes'][$key] = $variables[$key]; } } }

drupal8/core/includes/theme.inc

slide-85
SLIDE 85

/** * Prepares variables for image templates. */ function template_preprocess_image(&$variables) { if (!empty($variables['uri'])) { $variables['attributes']['src'] = file_url_transform_relative(file_create_url($variables['uri'])); } // There is normally a lot of code here that takes the responsive variables // and turns them into properly formatted attribute values. foreach (array('width', 'height', 'alt', 'title', 'sizes') as $key) { if (isset($variables[$key])) { // If the property has already been defined in the attributes, // do not override, including NULL. if (array_key_exists($key, $variables['attributes'])) { continue; } $variables['attributes'][$key] = $variables[$key]; } } }

drupal8/core/includes/theme.inc

slide-86
SLIDE 86

<img{{ attributes }} />

drupal8/core/themes/stable/templates/field/image.html.twig

slide-87
SLIDE 87

{% set classes = [ 'node', 'node--type-' ~ node.bundle|clean_class, node.isPromoted() ? 'node--promoted', node.isSticky() ? 'node--sticky', not node.isPublished() ? 'node--unpublished', view_mode ? 'node--view-mode-' ~ view_mode|clean_class, ] %} {{ attach_library('classy/node') }} <article{{ attributes.addClass(classes) }}> // Node markup. </article>

drupal8/core/themes/classy/templates/content/node.html.twig

slide-88
SLIDE 88

Theme System

(Erin Khoo, Flickr)

slide-89
SLIDE 89

/** * Implements hook_theme(). */ function system_theme() { return array( 'image' => array( 'variables' => array( 'uri' => NULL, 'width' => NULL, 'height' => NULL, 'alt' => '', 'title' => NULL, 'attributes' => array(), 'sizes' => NULL, 'srcset' => array(), 'style_name' => NULL, ), ), ); }

drupal8/core/modules/system/system.module drupal8/core/includes/theme.inc (simplified)

slide-90
SLIDE 90

// A responsive image render array in D8. $logo_uri = 'public://logo.png'; $logo = array( '#theme' => 'image', '#uri' => $logo_uri, '#alt' => t('My logo!'), '#sizes' => '100vw', '#srcset' => array( array( 'uri' => ImageStyle::load('thumbnail')->buildUri($logo_uri), 'width' => '250w', ), array( 'uri' => ImageStyle::load('large')->buildUri($logo_uri), 'width' => '750w', ), ), );

slide-91
SLIDE 91

// Printing/rendering our logo in D8. {{ logo }}

slide-92
SLIDE 92

drupal8/core/includes/theme.inc

/** * Prepares variables for image templates. */ function template_preprocess_image(&$variables) { if (!empty($variables['uri'])) { $variables['attributes']['src'] = file_url_transform_relative(file_create_url($variables['uri'])); } // There is normally a lot of code here that takes the responsive variables // and turns them into properly formatted attribute values. foreach (array('width', 'height', 'alt', 'title', 'sizes') as $key) { if (isset($variables[$key])) { // If the property has already been defined in the attributes, // do not override, including NULL. if (array_key_exists($key, $variables['attributes'])) { continue; } $variables['attributes'][$key] = $variables[$key]; } } }

slide-93
SLIDE 93

<img{{ attributes }} />

drupal8/core/themes/stable/templates/field/image.html.twig

slide-94
SLIDE 94

// The resulting responsive image markup. <img src="logo.png" alt="My logo!" sizes="100vw" srcset="styles/thumbnail/public/logo.png 250w, styles/large/public/logo.png 750w">

slide-95
SLIDE 95

why are render arrays useful?

(ndrwfgg, Flickr)

slide-96
SLIDE 96

theme functions such as theme_image() hook_theme() defines theme hooks the theme() function

slide-97
SLIDE 97

theme functions such as theme_image() hook_theme() defines theme hooks the theme() function

slide-98
SLIDE 98

// Using theme() in Drupal 7. $logo = theme('image', array( 'path' => 'logo.png', 'alt' => t('My logo!'), ));

slide-99
SLIDE 99

https://api.drupal.org/api/drupal/includes!theme.inc/function/theme/7.x

slide-100
SLIDE 100

https://api.drupal.org/api/drupal/includes!theme.inc/function/theme/7.x

“Avoid calling this function directly. It is preferable to replace direct calls to the theme() function with calls to drupal_render() by passing a render array with a #theme key to drupal_render(), which in turn calls theme().”

slide-101
SLIDE 101

<?php if ($logo): ?> <a href="<?php print $front_page; ?>" title="<?php print t('Home'); ?>" rel="home" id="logo"> <img src="<?php print $logo; ?>" alt="<?php print t('Home'); ?>" /> </a> <?php endif; ?>

drupal7/modules/system/page.tpl.php

slide-102
SLIDE 102

<?php if ($logo): ?> <a href="<?php print $front_page; ?>" title="<?php print t('Home'); ?>" rel="home" id="logo"> <img src="<?php print $logo; ?>" alt="<?php print t('Home'); ?>" /> </a> <?php endif; ?>

drupal7/modules/system/page.tpl.php

slide-103
SLIDE 103

/** * Preprocess variables for page.tpl.php */ function template_preprocess_page(&$variables) { $variables['logo'] = theme_get_setting('logo'); }

drupal7/includes/theme.inc

slide-104
SLIDE 104

/** * Implements hook_preprocess_page(). */ function my_theme_preprocess_page(&$variables) { if (drupal_is_front_page()) { $variables['logo'] = 'logo-front.jpg'; } }

slide-105
SLIDE 105

<?php if ($logo): ?> <a href="<?php print $front_page; ?>" title="<?php print t('Home'); ?>" rel="home" id="logo"> <img src="<?php print $logo; ?>" alt="<?php print t('Home'); ?>" /> </a> <?php endif; ?>

drupal7/modules/system/page.tpl.php

slide-106
SLIDE 106

<?php if ($logo): ?> <a href="<?php print $front_page; ?>" title="<?php print t('Home'); ?>" rel="home" id="logo"> <?php print render($logo); ?> </a> <?php endif; ?>

theoretical drupal7/modules/system/page.tpl.php

slide-107
SLIDE 107

theoretical drupal7/includes/theme.inc

/** * Preprocess variables for page.tpl.php */ function template_preprocess_page(&$variables) { $variables['logo'] = theme('image', array( 'path' => theme_get_setting('logo'), 'alt' => t('Home'), )); }

slide-108
SLIDE 108

/** * Implements hook_preprocess_page(). */ function my_theme_preprocess_page(&$variables) { dpm($variables['logo']); }

slide-109
SLIDE 109

// The current state of the logo variable. <img src="logo.png" alt="Home" />

slide-110
SLIDE 110

/** * Implements hook_preprocess_page(). */ function my_theme_preprocess_page(&$variables) { $new_logo = str_replace(' />', ' class="logo" />', $variables['logo']); $variables['logo'] = $new_logo; }

slide-111
SLIDE 111

/** * Preprocess variables for page.tpl.php */ function template_preprocess_page(&$variables) { $variables['logo'] = array( '#theme' => 'image', '#path' => theme_get_setting('logo'), '#alt' => t('Home'), ); }

theoretical drupal7/includes/theme.inc

slide-112
SLIDE 112

/** * Implements hook_preprocess_page(). */ function my_theme_preprocess_page(&$variables) { dpm($variables['logo']); }

slide-113
SLIDE 113

// The current state of the logo variable. array( '#theme' => 'image', '#path' => 'logo.jpg', '#alt' => 'Home', );

slide-114
SLIDE 114

/** * Implements hook_preprocess_page(). */ function my_theme_preprocess_page(&$variables) { $variables['logo']['#attributes']['class'][] = 'logo'; }

slide-115
SLIDE 115

// The current state of the logo variable. array( '#theme' => 'image', '#path' => 'logo.jpg', '#alt' => 'Home', '#attributes' => array( 'class' => array('logo'), ), );

slide-116
SLIDE 116

<?php if ($logo): ?> <a href="<?php print $front_page; ?>" title="<?php print t('Home'); ?>" rel="home" id="logo"> <?php print render($logo); ?> </a> <?php endif; ?>

theoretical drupal7/modules/system/page.tpl.php

slide-117
SLIDE 117

// The resulting markup with our class. <img src="logo.png" alt="Home" class="logo" />

slide-118
SLIDE 118

problem: build feature X like the last site but slightly different

slide-119
SLIDE 119

// The current state of the logo variable. array( '#theme' => 'image', '#path' => 'logo.jpg', '#alt' => 'Home', );

slide-120
SLIDE 120

/** * Implements hook_preprocess_page(). */ function my_theme_preprocess_page(&$variables) { $variables['logo']['#attributes']['class'][] = 'logo'; }

slide-121
SLIDE 121

{% set classes = [ 'node', 'node--type-' ~ node.bundle|clean_class, node.isPromoted() ? 'node--promoted', node.isSticky() ? 'node--sticky', not node.isPublished() ? 'node--unpublished', view_mode ? 'node--view-mode-' ~ view_mode|clean_class, ] %} {{ attach_library('classy/node') }} <article{{ attributes.addClass(classes) }}> // Node markup. </article>

drupal8/core/themes/classy/templates/content/node.html.twig

slide-122
SLIDE 122

solution: abstraction

slide-123
SLIDE 123

(john mcsporran, Flickr)

the Render API

slide-124
SLIDE 124

Theme System? Render API?

slide-125
SLIDE 125

Theme System: hook_theme() hook_preprocess_HOOK() hook_theme_suggestions_HOOK() Twig templating engine

slide-126
SLIDE 126

Render API: Render arrays Render elements Caching Attachments Placeholders

slide-127
SLIDE 127

#theme #type #[variable] #cache #attached #weight #markup #prefix #suffix

slide-128
SLIDE 128

#theme #type #[variable] #cache #attached #weight #markup #prefix #suffix

slide-129
SLIDE 129

drupal8/core/lib/Drupal/Core/Render/theme.api.php

“The core structure of the Render API is the render array, which is a hierarchical associative array containing data to be rendered and properties describing how the data should be rendered.”

slide-130
SLIDE 130

Render API: Render arrays Render elements Caching Attachments Placeholders

slide-131
SLIDE 131

“Modules have the capability of defining elements, which are essentially prepackaged default render arrays.”

slide-132
SLIDE 132

/** * @FormElement("checkbox") */ class Checkbox extends FormElement { public function getInfo() { $class = get_class($this); return array( '#input' => TRUE, '#return_value' => 1, '#process' => array( array($class, 'processCheckbox'), array($class, 'processAjaxForm'), array($class, 'processGroup'), ), '#pre_render' => array( array($class, 'preRenderCheckbox'), array($class, 'preRenderGroup'), ), '#theme' => 'input__checkbox', '#theme_wrappers' => array('form_element'), '#title_display' => 'after', ); }

drupal8/core/lib/Drupal/Core/Render/Element/Checkbox.php

slide-133
SLIDE 133

/** * @FormElement("checkbox") */ class Checkbox extends FormElement { public function getInfo() { $class = get_class($this); return array( '#input' => TRUE, '#return_value' => 1, '#process' => array( array($class, 'processCheckbox'), array($class, 'processAjaxForm'), array($class, 'processGroup'), ), '#pre_render' => array( array($class, 'preRenderCheckbox'), array($class, 'preRenderGroup'), ), '#theme' => 'input__checkbox', '#theme_wrappers' => array('form_element'), '#title_display' => 'after', ); }

drupal8/core/lib/Drupal/Core/Render/Element/Checkbox.php

slide-134
SLIDE 134

// Our simple render element in D8. $form['setting'] = array( '#type' => 'checkbox', '#title' => t('Are we having fun yet?'), );

slide-135
SLIDE 135

// Our simple render element in D8. $form['setting'] = array( '#type' => 'checkbox', '#title' => t('Are we having fun yet?'), );

slide-136
SLIDE 136

// Our simple render element in D8. $form['setting'] = array( '#type' => 'checkbox', '#title' => t('Are we having fun yet?'), );

slide-137
SLIDE 137

/** * @FormElement("checkbox") */ class Checkbox extends FormElement { public function getInfo() { $class = get_class($this); return array( '#input' => TRUE, '#return_value' => 1, '#process' => array( array($class, 'processCheckbox'), array($class, 'processAjaxForm'), array($class, 'processGroup'), ), '#pre_render' => array( array($class, 'preRenderCheckbox'), array($class, 'preRenderGroup'), ), '#theme' => 'input__checkbox', '#theme_wrappers' => array('form_element'), '#title_display' => 'after', ); }

drupal8/core/lib/Drupal/Core/Render/Element/Checkbox.php

slide-138
SLIDE 138

/** * @FormElement("checkbox") */ class Checkbox extends FormElement { public function getInfo() { $class = get_class($this); return array( '#input' => TRUE, '#return_value' => 1, '#process' => array( array($class, 'processCheckbox'), array($class, 'processAjaxForm'), array($class, 'processGroup'), ), '#pre_render' => array( array($class, 'preRenderCheckbox'), array($class, 'preRenderGroup'), ), '#theme' => 'input__checkbox', '#theme_wrappers' => array('form_element'), '#title_display' => 'after', ); }

drupal8/core/lib/Drupal/Core/Render/Element/Checkbox.php

slide-139
SLIDE 139

// Our simple render element in D8. $form['setting'] = array( '#type' => 'checkbox', '#title' => t('Are we having fun yet?'), );

slide-140
SLIDE 140

/** * @FormElement("checkbox") */ class Checkbox extends FormElement { public function getInfo() { $class = get_class($this); return array( '#input' => TRUE, '#return_value' => 1, '#process' => array( array($class, 'processCheckbox'), array($class, 'processAjaxForm'), array($class, 'processGroup'), ), '#pre_render' => array( array($class, 'preRenderCheckbox'), array($class, 'preRenderGroup'), ), '#theme' => 'input__checkbox', '#theme_wrappers' => array('form_element'), '#title_display' => 'after', ); }

drupal8/core/lib/Drupal/Core/Render/Element/Checkbox.php

slide-141
SLIDE 141

The Form API is a subset

  • f the Render API.
slide-142
SLIDE 142

// Our simple render element in D8. $form['setting'] = array( '#type' => 'checkbox', '#title' => t('Are we having fun yet?'), );

slide-143
SLIDE 143

Render API: Render arrays Render elements Caching Attachments Placeholders

slide-144
SLIDE 144

// Caching a render array. '#cache' => array( 'keys' => array('entity_view', 'node', $node->id()), 'contexts' => array('languages'), 'tags' => array('node:' . $node->id()), 'max-age' => Cache::PERMANENT, ),

slide-145
SLIDE 145

Cacheability of render arrays

drupal.org/developing/api/8/render/arrays/cacheability

slide-146
SLIDE 146

// Attaching libraries and JS settings to render arrays. $build['#attached']['library'][] = 'core/jquery'; $build['#attached']['drupalSettings']['foo'] = 'bar';

slide-147
SLIDE 147

// Using placeholders in render array markup. $build['my_element'] = array( '#attached' => array('placeholders' => array('@foo' => 'replacement')), '#markup' => array('Something about @foo'), );

slide-148
SLIDE 148

// Using placeholders in render array markup. $build['my_element'] = array( '#attached' => array('placeholders' => array('@foo' => 'replacement')), '#markup' => array('Something about @foo'), );

slide-149
SLIDE 149

#theme #type #[variable] #cache #attached #weight #markup #prefix #suffix

slide-150
SLIDE 150

Render API: Render arrays Render elements Caching Attachments Placeholders

slide-151
SLIDE 151

the future

(Davis Doherty, Flickr)

slide-152
SLIDE 152

[meta] Refactor Render API to be OO

drupal.org/node/1843798

slide-153
SLIDE 153

Unify & simplify render & theme system: component-based rendering (enables pattern library, style guides, interface previews, client-side re-rendering)

drupal.org/node/2702061

slide-154
SLIDE 154

Unify & simplify render & theme system: component-based rendering (enables pattern library, style guides, interface previews, client-side re-rendering)

drupal.org/node/2702061

slide-155
SLIDE 155

Render arrays, the current theme system, and the current Render API may be removed from Drupal 9.

slide-156
SLIDE 156

I didn’t just waste an hour of your time.

slide-157
SLIDE 157

Render arrays are still important …for now. :)

slide-158
SLIDE 158

Render Arrays: what they look like how they work why they’re handy the Render API their future

slide-159
SLIDE 159

// Our simple render array in D8. $logo = array( '#theme' => 'image', '#uri' => 'public://logo.png', '#alt' => t('My logo!'), );

slide-160
SLIDE 160

/** * Implements hook_theme(). */ function system_theme() { return array( 'image' => array( 'variables' => array( 'uri' => NULL, 'width' => NULL, 'height' => NULL, 'alt' => '', 'title' => NULL, 'attributes' => array(), 'sizes' => NULL, 'srcset' => array(), 'style_name' => NULL, ), ), ); }

drupal8/core/modules/system/system.module drupal8/core/includes/theme.inc (simplified)

slide-161
SLIDE 161

// Printing/rendering anything in D8. {{ logo }}

slide-162
SLIDE 162

drupal8/core/includes/theme.inc

/** * Prepares variables for image templates. */ function template_preprocess_image(&$variables) { if (!empty($variables['uri'])) { $variables['attributes']['src'] = file_url_transform_relative(file_create_url($variables['uri'])); } // There is normally a lot of code here that takes the responsive variables // and turns them into properly formatted attribute values. foreach (array('width', 'height', 'alt', 'title', 'sizes') as $key) { if (isset($variables[$key])) { // If the property has already been defined in the attributes, // do not override, including NULL. if (array_key_exists($key, $variables['attributes'])) { continue; } $variables['attributes'][$key] = $variables[$key]; } } }

slide-163
SLIDE 163

<img{{ attributes }} />

drupal8/core/themes/stable/templates/field/image.html.twig

slide-164
SLIDE 164

// The resulting markup. <img src="logo.png" alt="My logo!" />

slide-165
SLIDE 165

/** * Implements hook_preprocess_page(). */ function my_theme_preprocess_page(&$variables) { $variables['logo']['#attributes']['class'][] = 'logo'; } my_theme/template.php

slide-166
SLIDE 166

// Our simple render/form element in D8. $form['setting'] = array( '#type' => 'checkbox', '#title' => t('Are we having fun yet?'), );

slide-167
SLIDE 167

#theme #type #[variable] #cache #attached #weight #markup #prefix #suffix

slide-168
SLIDE 168

// Caching a render array. '#cache' => array( 'keys' => array('entity_view', 'node', $node->id()), 'contexts' => array('languages'), 'tags' => array('node:' . $node->id()), 'max-age' => Cache::PERMANENT, ), // Attaching libraries and JS settings to render arrays. $build['#attached']['library'][] = 'core/jquery'; $build['#attached']['drupalSettings']['foo'] = ‘bar';

// Using placeholders in render array markup. $build['my_element'] = array( '#attached' => array('placeholders' => array('@foo' => 'replacement')), '#markup' => array('Something about @foo'), );

slide-169
SLIDE 169

Aha! Understanding and Using Render Arrays in Drupal 8

slide-170
SLIDE 170

further reading:

Render API Overview (8.x)

api.drupal.org/api/drupal/core!lib!Drupal!Core!Render! theme.api.php/group/theme_render/8.2.x

Theme system overview (8.x)

api.drupal.org/api/drupal/core!lib!Drupal!Core!Render! theme.api.php/group/themeable/8.2.x

Render Arrays in Drupal 7

drupal.org/node/930760

slide-171
SLIDE 171

further reading:

Render API Overview (8.x)

api.drupal.org/api/drupal/core!lib!Drupal!Core!Render! theme.api.php/group/theme_render/8.2.x

Theme system overview (8.x)

api.drupal.org/api/drupal/core!lib!Drupal!Core!Render! theme.api.php/group/themeable/8.2.x

Render Arrays in Drupal 7

drupal.org/node/930760