twig: friendly curly braces invade your templates!

Post on 11-May-2015

797 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

Video: http://youtu.be/Jikkiqt-nBo Twig! Yep, it's that fancy magic that's supposed to make theming in Drupal 8 as much fun as eating beef brisket at Rudy's Country Store in Austin (apologies to my veggie friends!). And in fact, Twig was *born* for this: a language that was created with one job in mind: making writing templates awesome and powerful. Oh, and to make you love using it. In this talk, we'll learn about Twig from the ground-up: syntax, filters, inheritance and other tricks you can learn now to be ready for Drupal 8. We'll also look at how Twig looks inside Drupal, and how it compares to what you're used to in Drupal 7. By the end, you'll know everything to start getting your Drupal 8 theme on and be shouting its praises from the hills! Ok, maybe not that last part (but I do love how excited Drupalers get), but you'll definitely have a new friend in your world: Twig.

TRANSCRIPT

Being dangerous with Twig

A guide to using Twig – the fast, secure andextensible PHP templating engine – to create clean

template code, leverage powerful filters, make your designerswrite you love letters, write template functions that Don't clog up your

global PHP namespace, take advantage of true template inheritance, hang out with Django programmers and be able to talk template syntax, enjoy true and non-invasive output escaping, have more time for your family, control whitespace, add global

variables to all templates, stop lying when you try to tell yourself that <?php echo looks better than asimple {{, use the fancy for-else control, Rock some macros – little reusable code functions, do awesome stuff like “{% if i is divisibleby 2 %}”,mediate in the simplicity of your templates and drink more green tea, sandbox your template and whitelist capabilities – allowing Twig to be used in a CMS,

take advantage of the fact that all templates compile to PHP classes that can extend a base class of your choosing, impress your friends by changing the print tag from{{ var }} to [all-your-base] var [are-belong-to-us], confuse the guy next to you by changing “is” and “is not” to mean the opposite things and convince him that he's misunderstood

how logical expressions are used in programming languages all along, create a custom tag that takes the body of its block and tweets it,write templates the expresses presentation and not program logic.

Being dangerous with Twig

KnpUniversity.comgithub.com/weaverryan

• Lead for the Symfony documentation!

• KnpLabs US - Symfony consulting, training, Kumbaya!

• Writer for KnpUniversity.comscreencasts

Buenos Dias!

Birthday Wishes!

Happy Birthday Dad!

Happy Birthday Anne-Sophie!

Happy Birthday Rafael Nadal

Happy Birthday Anderson Cooper

Why Twig?

Act 1

@weaverryan

because template engines are awesome

@weaverryan

$engine = new RyansFantasyTemplatingEngine();$tpl = $engine->loadTemplate('drupalcon.php'); $tpl->render([‘place' => ‘Austin!’]);

<!-- drupalcon.php --><h1><?php echo $place ?></h1><?php echo call_some_great_helper('woot!') ?>

Template Engines

• A template engine allows you to render a presentation (HTML, XML, etc) via a template in a controlled environment!

• It should allow special functionality that makes creating templates easier (helpers, template inheritance, etc)

@weaverryan

@weaverryan

a template engine is a tool

@weaverryan

why not just render PHP templates?

PHP templating woes

• rendering template files is a hack: an include statement with output-buffering control

!

• no or faked template inheritance!

• no isolation: PHP templates suck in any global variables or functions available

@weaverryan

@weaverryan

we want the brevity of templates

!

with the isolation of object-oriented programming

@weaverryan

so give me some Twiggy pudding

Twig is:» fast» flexible» concise» secure» fully-featured» Extensible» designer-friendly

Twig offers:» true inheritance» real output escaping» tons of filters» custom tags» great documentation» global variables» the “for-else” control

@weaverryan

Twig is concise !

and each template compiles to an actual

PHP object

@weaverryan

Seeing is believing

https://www.flickr.com/photos/visitfinland/5203910918

@weaverryan

because template engines are awesome

@weaverryan

because template engines are awesome

@weaverryan

because template engines are awesome

class __TwigTemplate_617db133b9dd01ce28b55447b extends Twig_Template{ // line 3 public function block_body($context, array $blocks = array()) { // line 4 echo " "; foreach ($context['_seq'] as $context["_key"] => $context["blog"]) { // line 5 echo " <h2>"; echo $this->getAttribute($context["blog"]); echo "</h2>

@weaverryan https://www.flickr.com/photos/melolou/517629486

a moment of templating zen

@weaverryan

“The template system is meant to express presentation, not

program logic.”- Django Documentation

@weaverryan

Twig can easily be used anywhere

@weaverryan

require __DIR__.'/vendor/autoload.php'; $loader = new Twig_Loader_Filesystem(array(__DIR__.'/templates'));$twig = new Twig_Environment($loader); echo $twig->render('hello.twig', array( 'name' => 'DrupalCon!'));

{# templates/hello.twig #} {% extends 'layout.twig' %}{% block body %} Hello {{ name }}!{% endblock %}

Act 2

Twig’s Simple Life

@weaverryan

Twig's three tags

Twig parses just three tags:!

» comment tag!

» print tag!

» block tag

a. do nothing (comment tags)

{# comment #}» totally ignored when rendered

@weaverryan

b. say something (print tags)

{{ 'print me!' }}» simply prints the given expression» equivalent to <?php echo» If you're ultimately printing something,

use this tag

@weaverryan

@weaverryan

c. do something (block tags)

{% set foo = 'inside a block tag' %}» used mostly for control-flow statements like if,

for, include and block» can have beginning and end tags» if you're *doing* something and not *printing*

something, use this tag

@weaverryan

Twig’s three tags

!

» do nothing: {# comment tag #}» say something {{ ‘print tag’ }}» do something {% block tag %}

It’s just that simple!

Act 3

Everything is an expression

@weaverryan

expressions Twig guts

» like PHP, most everything inside a tag is an expression!

!

!

!

!

» expressions are the most interesting and flexible part of Twig

@weaverryan

Expressions Block names Block-specific tokens

@weaverryan

An expression can consist of many different things

https://www.flickr.com/photos/swambo/7617988518

@weaverryan

strings, numbers and variables

» like any language, strings, numbers and variables are commonplace

@weaverryan

arrays and hashes

» arrays use [], hashes use {}

@weaverryan

operators

» just like PHP operators, but extensible

@weaverryan

filters

» filters modify the value that precedes it and are always preceded by a pipe (|)

» filters may or may not take arguments

@weaverryan

functions

» returns a value based on an arbitrary input

@weaverryan

» strings, numbers and variables » arrays and hashes » operators » filters » functions

allow Twig to express Twig’s-self

Hey! It’s simple like PHP, but flexible

Act 4

Twig on the battlefield

@weaverryan

» a template that displays a list of “widgets” in odd-even rows

» render info about each widget

» create basic, clean pagination

the test…

@weaverryan

@weaverryan http

://1.

bp.b

logs

pot.c

om/_

D_Z-

D2tz

i14/

TBpO

nhVq

yAI/A

AAAA

AAAD

FU/8

tfM4E

_Z4p

U/s

1600

/resp

onsi

bilit

y12(

alte

rnat

e).p

ng

@weaverryan

@weaverryan

» the “truncate” filter isn't part of Twig, but is available via a library of extensions

» Everything in Twig is loaded via an Extension (even the core stuff)

» Extensions are easy to use and create – we’ll prove it later!

» https://github.com/fabpot/Twig-extensions

your presenter is lying to you…

@weaverryan http

://1.

bp.b

logs

pot.c

om/_

D_Z-

D2tz

i14/

TBpO

nhVq

yAI/A

AAAA

AAAD

FU/8

tfM4E

_Z4p

U/s

1600

/resp

onsi

bilit

y12(

alte

rnat

e).p

ng

@weaverryan

@weaverryan https://www.flickr.com/photos/circasassy/7192588208

Flex some filters

@weaverryan

@weaverryan

convenience, readability

@weaverryan

@weaverryan

pagination?

@weaverryan

@weaverryan

» but.... the “radius” function doesn't actually exist in Twig.

the audacity: your speaker just lied again

But since it's pretty handy, let's create it!

Act 5

Twig extensions!

@weaverryan

» filters» functions» operators» tests (e.g. divisibleby)» custom tags

Twig extensions

everything in Twig is loaded by an “Extension” class:

Extensions are easy!

@weaverryan

@weaverryan

Yes, there is a missing piece of “hooking this up”

@weaverryan

It’s a small amount of code, involving services

@weaverryan

Come to my talk tomorrow ;)

!

MASTER THE NEW CORE OF DRUPAL 8 NOW: WITH SYMFONY

AND SILEX !

10:45 Room: G - Trellon | 4th floor

Act 6

Theming D7 versus D8

@weaverryan

Good News!

@weaverryan

The Changes are Underwhelming!

@weaverryan

From D7 themes to D8 themes

» Other than the Twig syntax, things feel very familiar!

» page.tpl.php -> page.html.twig» node.tpl.php -> node.html.twig» THEME.info -> THEME.info.yml !

» THEME_field__taxonomy_term_reference() -> field--taxonomy-term-reference.html.twig

@weaverryan

<div id="node-<?php print $node->nid; ?>" clearfix"<?php print $attributes; ?>> <?php print render($title_prefix); ?> <div class="content clearfix"<?php print $content_attributes; ?>> <?php hide($content['links']); print render($content); ?> </div> <?php $links = render($content['links']); if ($links): ?> <div class="link-wrapper"> <?php print $links; ?> </div> <?php endif; ?> </div>

D7: node.tpl.php

@weaverryan

<article id="node-{{ node.id }}” role=“article" {{ attributes|without(‘id', 'role') }}> <header>{{ title_prefix }}</header> <div class="content clearfix"{{ content_attributes }}> {{ content|without('links') }} </div> {% if content.links %} <footer class="link-wrapper"> {{ content.links }} </footer> {% endif %}</article>

D8: node.html.twig

@weaverryan

Function overrides

@weaverryan

D7: template.php

function bartik_field__taxonomy_term_reference($variables) { $output = ''; // Render the label, if it's not hidden. if (!$variables['label_hidden']) { $output .= '<h3 class="field-label">' . $variables['label'] . ': </h3>'; } // Render the items. $output .= ($variables['element']['#label_display'] == 'inline') ? '<ul class="links inline">' : '<ul class="links">'; foreach ($variables['items'] as $delta => $item) { $output .= '<li class="taxonomy-term-reference-' . $delta . '"' . $variables['item_attributes'][$delta] . '>' . drupal_render($item) . '</li>'; } $output .= '</ul>';

@weaverryan

D8: field--taxonomy-term-reference.html.twig

<div class="{{ attributes.class }} clearfix” {{ attributes|without('class') }}> <h3{{ label_attributes }}>{{ label }}: </h3> <ul class="links"> {% for delta, item in items %} <li class="taxonomy-term-reference-{{ delta }}"{{ item_attributes[delta] }}>{{ item }}</li> {% endfor %} </ul> </div>

Act 7

after-dinner mint

Mmmmm…..

@weaverryan

Debugging

@weaverryan

/** * settings.php * * Twig debugging: * * When debugging is enabled: * - The markup is surrounded by HTML comments * - The dump() function can be used * - Templates are automatically recompiled */$settings['twig_debug'] = TRUE;

@weaverryan

… inline suggestions about the template to override …

@weaverryan

… dump *all* variables you have access to …

@weaverryan

<article id="node-{{ node.id }}" ...> {{ dump() }} {# ... #}</article>

@weaverryan

… or just dump the names of the variables …

@weaverryan

<article ...> {{ dump(_context|keys) }} </article>

@weaverryan

Inheritance

@weaverryan

{% block header %}<header> {{ title_prefix }} {% if not page %} <h2{{ title_attributes }}> <a href="{{ node_url }}">{{ label }}</a> </h2> {% endif %} {{ title_suffix }} {% if display_submitted %} <div class="meta submitted"> {{ user_picture }} {{ submitted }} </div> {% endif %}</header>{% endblock %}

node.html.twig

@weaverryan

{% extends "core/themes/bartik/templates/node.html.twig" %}{% block header %} <h1 class="header">{{ label }}</h1>{% endblock %}

node--article.html.twig

@weaverryan

{% extends "core/themes/bartik/templates/node.html.twig" %}{% block header %} <div class="article"> {{ parent() }} </div>{% endblock %}

node--article.html.twig

@weaverryan

dot.notation

@weaverryan

Am I working with an array?

<?php print render($page['header']); ?>

<div id="node-<?php print $node->nid; ?>">

or an object?

@weaverryan

Am I working with an array?

who cares!?

<article id="node-{{ node.id }}">

{{ page.header }}

@weaverryan

{{ page.header }}

» The dot notation is smart!!

A. Is this an object with a public property?B. Is this an array that has this key?C. Is there a getHeader() function I can call?

@weaverryan

Templates in the Database

@weaverryan

Twig.js

@weaverryan

A twig template can *also* be rendered in

JavaScript

@weaverryan

<script src="/js/twig.js"> <script> var template = twig({ data: 'The {{ baked_good }} is a lie.' }); console.log( template.render({ baked_good: ‘cupcake' }) ); // outputs: "The cupcake is a lie."</script>

@weaverryan

https://github.com/justjohn/twig.js/

Ryan Weaver @weaverryan

¡Gracias!

top related