Render API en D7 & D8
About me
Jose Luis Bellido
http://www.traslaniebla.com/wp-content/uploads/2012/05/got1.png
El terreno de juego
El código más allá del muro
global $user;
$account = user_load($user->uid);
$output = '<div class="logged-user-info">';
// User picture:
$output .= "<a href='/user/$account->uid'>";
$output .= "<img src='/sites/default/files/pictures/" . $account->picture->filename ."'>";
$output .= "</a>";
// User roles:
$output .= '<ul>';
foreach($user->roles as $rid => $role) {
$output .= '<li>'. $role .'</li>';
}
$output .= '</ul>';
// User achievements:
$output .= '<div class="user-achievements">';
$output .= '<span class="user-points">' . t('User points: @points', array('@points' => 4)) . '</span>';
$output .= '<span class="highlighted-achievement">';
$output .= t('Highest score: @score', array('@score' => 16));
$output .= '</span>';
$output .= '</div>';
$output .= '</div>';
return $output;
}
El caminante blanco
El código stark
global $user;
$output = '<div class="logged-user-info">';
// User picture:
$output .= theme('user_picture', array('account' => $user));
// User roles:
$output .= theme('item_list', array('items' => $user->roles));
// User achievements:
$output .= theme('user_achievements', array('points' => 4,'score' => 16));
$output .= '</div>';
// Add custom css & js:
drupal_add_js(drupal_get_path('module', 'render_examples') . '/js/user_achievements.js');
drupal_add_css(drupal_get_path('module', 'render_examples') . '/css/user_achievements.css');
return $output;
El código stark
El código Targaryan
Los render arrays
global $user;
$render = array(
'user-picture' => array(
'#theme' => 'user_picture',
'#account' => $user,
),
'item-list' => array(
'#theme' => 'item_list',
'#items' => $user->roles,
),
'user-achievements' => array(
'#theme' => 'user_achievements',
'#points' => 4,
'#score' => 16,
'#attached' => array(
'js' => array(drupal_get_path('module', 'render_examples') . '/js/user_achievements.js'),
'css' => array(drupal_get_path('module', 'render_examples') . '/css/user_achievements.css'),
),
),
'#attributes' => array('class' => array('logged-user-info')),
'#theme_wrappers' => array('container'),
);
Introducción a los Render arrays
Render API: ¿Qué es?
- La base del Theme System de Drupal.
- Array asociativo jerarquizado.
- El heredero del sistema de renderizado de Form API.
¿Ventajas?
- Los datos pueden ser alterados por otros módulos.
- Cache.
- Themes envoltura.
- Más reusable.
- Uniformamos.
¿Inconvenientes?
- Periodo de adaptación.
- Más difícil de debugear.
- Arrays inmensos. => Divide y vencerás.
Render API & Forms API
- Forms API usa render API
- Render() para renderizar casi todo.
Propiedades
- #type hook_element_info()
- #access
- #theme_wrappers
- #pre_render
- #attached
Más en Form API Reference
Render API & Theming
- #theme : Función de render
- Variable theme => #variable
$themes['user_achievements'] = array(
'path' => drupal_get_path('module', 'render_examples') . '/templates',
'template' => 'user-achievements',
'variables' => array(
'points' => '',
'score' => '',
),
);
1.- Definimos nuestra función de theme :
Render API & Theming
'user-achievements' => array(
'#theme' => 'user_achievements',
'#points' => 4,
'#score' => 16,
'#attached' => array(
'js' => array(drupal_get_path('module', 'render_examples') . '/js/user_achievements.js'),
'css' => array(drupal_get_path('module', 'render_examples') . '/css/user_achievements.css'),
),
),
$render = array(
'#markup' => theme('user_achievements', array('points' => 4,'score' => 16)),
);
Definimos nuestro render array
¿Cómo lo haríais?
Exprimiendo Render API
Theme Wrappers
- Funciones theme de envoltura.
¿Ventajas?
- Normalizamos y reutilizamos.
- Acceso a todos los atributos.
- Se pueden anidar.
- Nos centramos sólo en el contenido.
- #prefix #suffix?
¿Inconvenientes?
- No documentadas las ya existentes.
- Cuidado! #theme_wrappers!
- Orden de izquierda a derecha
'#theme_wrappers' => array('container'),
'#theme_wrappers' => array('container', 'render_array'),
Crear nuestro theme wrapper
$themes['render_add_span'] = array(
'render element' => 'element',
);
1.- Defino el theme (hook_theme())
2.- Implementamos
/**
* Implements theme_THEME().
*/
function theme_render_add_span(&$variables) {
$element = $variables['element'];
$output = '<span class="render-wrapper-span">';
$output .= $element['#children'];
$output .= '</span>';
return $output;
}
3.- Lo añadimos
'#theme_wrappers' => array('container', 'render_add_span'),
Crear nuestro Theme_wrapper
El resultado
Attached Libraries, CSS & JS
-
No más drupal_add_js , drupal_add_css
-
No más en hook_init o sitios ocultos.
-
Sólo se carga cuando lo necesitas.
-
Ejemplo de uso AJAX
'#attached' => array(
'js' => array(drupal_get_path('module', 'render_examples') . '/js/user_achievements.js'),
'css' => array(drupal_get_path('module', 'render_examples') . '/css/user_achievements.css'),
),
drupal_add_js(drupal_get_path('module', 'render_examples') . '/js/user_achievements.js');
drupal_add_css(drupal_get_path('module', 'render_examples') . '/css/user_achievements.css');
'element_cached' => array(
'#markup' => '',
'#pre_render' => array('render_element_cached_pre_render'),
'#cache' => array(
'keys' => array('render_examples', 'cache-element'),
'bin' => 'cache',
'expire' => time() + 10,
'granularity' => DRUPAL_CACHE_PER_PAGE | DRUPAL_CACHE_PER_USER,
),
),
Caching with Render API
1.- Definición
2.- El truco
/**
* Custom pre_render callback for caching example.
* @param $element
* @return mixed
*/
function render_element_cached_pre_render($element) {
$element['#markup'] = render_elements_expensive();
$element['#children'] = $element['#markup'];
return $element;
}
Render API en Drupal 8
- Pocas diferencias con Drupal 7
-
Podemos definir 3 tipos de elementos
- #type : Elementos render. (ejm Form elements)
- #theme : Data of a theme hook.
- #markup : Para elementos sencillos.
- Mejoras en cache
- Sistema de plugins para definir render elements.
Render API en Drupal 8
Render API overview https://api.drupal.org/api/drupal/core!modules!system!theme.api.php/group/theme_render/8
Render API en Drupal 8
$renderer = \Drupal::service('renderer');
$config = \Drupal::config('system.site');
$current_user = \Drupal::currentUser();
$build = [
'#prefix' => '<aside>',
'#markup' => t('Hi, %name, welcome back to @site!', [
'%name' => $current_user->getUsername(),
'@site' => $config->get('name'),
]),
'#suffix' => '</aside>',
'#cache' => [
'contexts' => [
// The "current user" is used above, which depends on the request,
// so we tell Drupal to vary by the 'user' cache context.
'user',
],
],
];
// Merges the cache contexts, cache tags and max-age of the config object
// and user entity that the render array depend on.
$renderer->addCacheableDependency($build, $config);
$renderer->addCacheableDependency($build, \Drupal\user\Entity\User::load($current_user->id()));
?>
Render Elements Drupal 8
- Render elements son plugins!
- No se borra hook_element_info().
- Declaracion con anotaciones
-
Generic elements
- Extends RenderElement
-
Form input elements
- FormElement
Tipos de render elements
https://api.drupal.org/api/drupal/core%21modules%21system%21core.api.php/group/plugin_api/8
Theme_wrappers en Drupal 8
- Practicamente igual que en Drupal 7
- Tenemos attributos propios del theme_wrapper!!
array(
'#theme' => 'image',
'#attributes' => array('class' => 'foo'),
'#theme_wrappers' => array(
'container' => array(
'#attributes' => array('class' => 'bar'),
),
'custom_container' => array(
'#attributes' => array('class' => 'baz'),
),
),
);
https://www.drupal.org/node/2066209
Hagamos recopilatorio
- No reinventes la rueda: usala!
- Organiza cómo renderizar tu output.
- Evita usar theme().
- Separa en elementos renderables
- Usa los theme_wrappers para unificar
- Cachea los elementos con mucha carga.
Resources
Material de esta charla
Fuentes y otros recursos.
¿ Preguntas ?
Render API Drupal 7 & 8
By jlbellido
Render API Drupal 7 & 8
Charla sobre Render API en Drupal 7 & 8. Esta sesión tuvo lugar en la DrupalCampSpain Jerez 2015 (http://2015.drupalcamp.es). La charla fue grabada y está disponible en https://vimeo.com/128716914
- 2,799