Introduction to Twig
Upcoming SlideShare
Loading in...5
×
 

Introduction to Twig

on

  • 3,931 views

 

Statistics

Views

Total Views
3,931
Views on SlideShare
3,888
Embed Views
43

Actions

Likes
5
Downloads
59
Comments
0

4 Embeds 43

https://twitter.com 26
http://lanyrd.com 11
http://www.php-talks.com 5
https://mail.google.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Introduction to Twig Introduction to Twig Presentation Transcript

    • TWIGSaturday, 3 November, 12
    • ABOUT ME Team lead at FreshBooks Lead Developer of CakePHP Contributor to TwigSaturday, 3 November, 12
    • WHAT IS IT Templating language for PHP. Uses syntax and ideas from jinja2. Flexible and extensible at every layer.Saturday, 3 November, 12
    • BUT PHP IS A TEMPLATING LANGUAGE DUMMYSaturday, 3 November, 12
    • PHP SUCKS FOR TEMPLATING // In Plain PHP <?php echo $var; ?> (XSS you lose) <?php echo htmlspecialchars($var, ENT_QUOTES, ‘UTF-8’); ?> <?php echo h($var); ?> (sugar for htmlentities) // In Twig - autoescaping enabled {{ var }}Saturday, 3 November, 12
    • BENEFITS OF TWIG Terse syntax, and sugar. Automatic HTML escaping. Sandbox mode, which enables user editable templates. Ability to create custom DSL’s using application tags, operators and functions.Saturday, 3 November, 12
    • PLAIN PHP VS TWIGSaturday, 3 November, 12
    • CONDITIONALS // In Plain PHP <?php if (!empty($var): ?> ... <?php endif; ?> // In Twig {% if var %} ... {% endif %}Saturday, 3 November, 12
    • LOOPS <?php if (!empty($var): foreach ((array)$var as $i => $v): printf( ‘%s : %s’, htmlspecialchars($i, ENT_QUOTES, ‘UTF-8’), htmlspecialchars($v, ENT_QUOTES, ‘UTF-8’)); endforeach; else: echo ‘No things’; endif;Saturday, 3 November, 12
    • LOOPS {% for i, v in var %} {{ i }} : {{ v }} {% else %} No things {% endfor %}Saturday, 3 November, 12
    • LOOPS {% for user in users if user.active %} {{ user.name }} : {{ user.email }} {% else %} No active users {% endfor %}Saturday, 3 November, 12
    • BUT WAIT THERE IS MORESaturday, 3 November, 12
    • AWESOME++ Macros. Blocks & extending templates.Saturday, 3 November, 12
    • MACROS {% macro username(user) %} <a href=”{{ url({ ‘controller’: ‘users’, ‘action’: ‘view’, user.username) }}”> <span class=”user-first-name”> {{ user.first_name }} </span> <span> class=”user-last-name”> {{ user.last_name }} </span> </a> {% endmacro %}Saturday, 3 November, 12
    • IMPORTING MACROS // import all the macros {% import ‘/import/formatting.twig’ as formatting %} {{ formatting.username(user) }} // import one macro {% from ‘/import/formatting.twig’ import username %} {{ username(user) }} // import one & alias it. {% from ‘/import/formatting.twig’ import username as un %} {{ un(user) }}Saturday, 3 November, 12
    • INHERITANCE & BLOCKS Extending views & blocks work hand in hand. Blocks are like slots or holes in a template, that the child can fill. Blocks can be used out of order, which is pretty sweet. Blocks can be imported from other templates, similar to traits.Saturday, 3 November, 12
    • INHERITANCE {# layout/base.twig #} Company X - Official Email template {% block content ‘Super important’ %} Copyright 2012Saturday, 3 November, 12
    • INHERITANCE {# email/winner.twig #} {% extend ‘/layout/base.twig’ %} {% block content %} To whom it may concern, You win! {% endblock %}Saturday, 3 November, 12
    • INHERITANCE {# email/winner.twig #} {% extend ‘/layout/base.twig’ %} {% block content %} To whom it may concern, {{ parent() }} You win! {% endblock %}Saturday, 3 November, 12
    • INHERITANCE TIPS Don’t use {% block %} inside a loop. It doesn’t do what you want. You can use {{ block(name) }} to dynamically call blocks.Saturday, 3 November, 12
    • EXTENDING TWIG TWIG EXTENSIONSSaturday, 3 November, 12
    • EXTENDING TWIG Twig can be extended in several ways. Filters, Functions, Globals, Tests, Operators, TokenParsers, NodeVisitors. You should use extensions to package up your enhancements.Saturday, 3 November, 12
    • TWIG EXTENSIONSSaturday, 3 November, 12
    • LOADING EXTENSIONS $loader = new Twig_Loader_FileSystem(APP . ‘/templates’); $twig = new Twig_Environment($loader, $options); $twig->addExtension(new App_Extension_Url());Saturday, 3 November, 12
    • ENVIRONMENT FACTORY class AppTwig { static function loadTemplate($template, $options = array()) { $loader = new Twig_Loader_FileSystem(APP . ‘/templates’); $twig = new Twig_Environment($loader, $options); $twig->addExtension(new App_Extension_Url()); // Load more extensions return $twig->loadTemplate($template); } } $template = AppTwig::loadTemplate(‘/users/profile.twig’);Saturday, 3 November, 12
    • EXTENSION EXAMPLE <?php class App_Extension_Url extends Twig_Extension { public function getName() { return ‘app.url’; } public function getFilters() { return array( ‘name’ => new Twig_Filter_Method($this, ‘formatName’), ); } }Saturday, 3 November, 12
    • GLOBALS Can be used to expose application or framework objects. Great for migrating an older codebase to use Twig. E.g {{ html.link(...) }}Saturday, 3 November, 12
    • FUNCTIONS Global functions added to a template context. Great for providing shortcuts to application features, like url generation or built-in PHP functions. Example {{ form_input(model, ‘name’) }}Saturday, 3 November, 12
    • FILTERS Filters are intended for simple formatting functions. The filtered variable is the first argument to the filter function. Filters can have additional arguments as well. Example: {{ invoice.amount|currency(‘CAD’) }}Saturday, 3 November, 12
    • TESTS Allow you to implement custom conditional logic. In an expressive manner with domain objects. Value being compared is supplied as the first argument. Other arguments follow. {% if user is paying %} {% if number is divisibleby(3) %}Saturday, 3 November, 12
    • NODE VISITORS Allows you to visit each node in the Abstract syntax tree. Applied before template is compiled. Commonly used for optimizing the AST, or applying transformations to, or reading data from nodes in the tree.Saturday, 3 November, 12
    • CUSTOM TAGSSaturday, 3 November, 12
    • TWIG INTERNALS ENVIRONMENT LOADERSaturday, 3 November, 12
    • TWIG INTERNALS ENVIRONMENT LEXER LOADERSaturday, 3 November, 12
    • TWIG INTERNALS ENVIRONMENT LEXER LOADER TOKENSSaturday, 3 November, 12
    • TWIG INTERNALS ENVIRONMENT LEXER PARSER LOADER TOKENSSaturday, 3 November, 12
    • TWIG INTERNALS ENVIRONMENT LEXER PARSER LOADER TOKENS NODESSaturday, 3 November, 12
    • TWIG INTERNALS ENVIRONMENT LEXER PARSER COMPILER LOADER TOKENS NODESSaturday, 3 November, 12
    • TWIG INTERNALS ENVIRONMENT LEXER PARSER COMPILER LOADER TOKENS NODES PHP CODESaturday, 3 November, 12
    • TOKEN PARSERS Used to implement custom tags or DSL features. The most complex feature to add. Each tag is composed of two parts: TokenParser - parses the tag and validates its syntax. Node - Added to the AST and compiles the PHP code used in templates.Saturday, 3 November, 12
    • TAG EXAMPLE {% debug %} {% debug my_var %} {% debug 2 > 1 %}Saturday, 3 November, 12
    • TOKEN PARSER class App_TokenParser_Debug extends Twig_TokenParser { public function parse(Twig_Token $token) { $line = $token->getLine(); $expr = null; if (!$this->parser->getStream()->test(Twig_Token::BLOCK_END_TYPE)) { $expr = $this->parser->getExpressionParser->parseExpression(); } $this->parse->getStream()->expect(Twig_Token::BLOCK_END_TYPE); return new App_Node_Debug($expr, $line, $this->getTag()); } }Saturday, 3 November, 12
    • NODE COMPILER class App_Node_Debug extends Twig_Node { public function __construct(Twig_Node_Expression $ex, $line, $tag) { parent::__construct(array(‘expr’ => $ex), $line, $tag); } public function compile(Twig_Compiler $compiler) { $compiler->write(‘if ($this->env->isDebug()) {‘); if ($this->getNode(‘expr’) === null) { // Print all vars. } else { $compiler->write(‘var_dump(‘) ->subcompile($this->getNode(‘expr’)) ->raw(‘);’); } $compiler->write(‘}’); } }Saturday, 3 November, 12
    • OPERATORS Allow you to add additional boolean operators. I’ve never used this feature.Saturday, 3 November, 12
    • DEPLOYING TWIGSaturday, 3 November, 12
    • TWIG IN PRODUCTION FreshBooks (the app, not the website). 520+ templates. Twig templates are used for almost all HTML & E-mail content.Saturday, 3 November, 12
    • TEMPLATE COMPILATION TWIGSaturday, 3 November, 12
    • TEMPLATE COMPILATION TWIG PHPSaturday, 3 November, 12
    • TEMPLATE COMPILATION TWIG PHP HTMLSaturday, 3 November, 12
    • TEMPLATE COMPILATION TWIG PHP HTML Saved to diskSaturday, 3 November, 12
    • TEMPLATE COMPILATION PHP HTML Saved to diskSaturday, 3 November, 12
    • HOW WE DEPLOYSaturday, 3 November, 12
    • HOW WE DEPLOY COPY FILESSaturday, 3 November, 12
    • HOW WE DEPLOY COPY COMPILE FILES / BUILDSaturday, 3 November, 12
    • HOW WE DEPLOY COPY COMPILE SYMLINK FILES / BUILDSaturday, 3 November, 12
    • PRECOMPILE SCRIPT $directory = new RecursiveDirectoryIterator($argv[0]); $recurser = new RecursiveIteratorIterator($directory); $matcher = new RegexIterator( $recurser, /.*?.twig$/, RegexIterator::GET_MATCH); echo "Compiling Templatesn"; $i = 0; foreach ($matcher as $file) { $filename = str_replace($argv[1], , $file[0]); AppTwig::loadTemplate(/ . $filename); echo .; $i++; } echo "nTemplates compiledn"; exit(0);Saturday, 3 November, 12
    • TWIG C EXTENSION You can also install ext/twig. This pushes the most frequently used method Twig_Template::getAttribute() into C which increases performance considerably. The C extension is in the Twig repository.Saturday, 3 November, 12
    • QUESTIONS?Saturday, 3 November, 12
    • THANKS @MARK_STORY HTTP://MARK-STORY.COMSaturday, 3 November, 12