Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Enough about Classes, Let's Talk Templates

Enough about Classes, Let's Talk Templates

Jonathan Reinink

May 20, 2015
Tweet

More Decks by Jonathan Reinink

Other Decks in Technology

Transcript

  1. Jonathan Reinink Software developer from Canada Been writing PHP for

    about 15 years Marketing agency for over a decade Started contract development this year Leadership group of The PHP League Wrote the Plates template library Wrote the Glide image library I <3 open source
  2. “This blog post is not for the faint- hearted! Some

    people will strongly disagree with me and some others will probably want to kill me at the upcoming Zend Conference.” —Fabien Potencier
  3. “I'm not suggesting that native PHP templates are better than

    compiled templates (like Twig).” —Me
  4. “oh... puts the pitchfork down” —Friendly Reddit reader “hides torch

    behind back…” —Another friendly Reddit reader
  5. <html> ! <h1>Hello, <?=$name?></h1> ! <ul> <?php if ($stmt =

    $mysqli->prepare("SELECT name FROM friends")) { $stmt->execute(); $stmt->bind_result($name); ! while ($stmt->fetch()) { echo '<li>'.$name.'</li>'; } } ?> </ul>
  6. While PHP has evolved into a mature, object oriented language,

    it hasn’t improved much as a templating language.
  7. {% extends "template.html" %} ! {% block title %}User Profile{%

    endblock %} ! {% block content %} <h1>User Profile</h1> <p>Hello, {{ name }}</p> {% endblock %}
  8. You can write good template code with most modern templating

    libraries. Twig, Blade, Smarty, Moustache, Plates, Aura.View, Zend\View, etc…
  9. Choose a templating language with an easy learning curve. Easy

    for both server-side developers and front-end developers.
  10. <?php if ($items): ?> <?php foreach ($items as $item): ?>

    <li><?php echo $item ?></li> <?php endforeach ?> <?php else: ?> <li>No items found.</li> <?php endif ?> {% for item in items %} <li>{{ item }}</li> {% else %} <li>No items found.</li> {% endfor %} Native PHP Twig
  11. Never use blocks of PHP. <?php foreach ($users as $user)

    { echo $user->name; } ?> <?php foreach ($users as $user): ?> <?=$user->name?> <?php endforeach ?>
  12. Only one statement per PHP tag. <?php if ($users) {

    foreach ($users as $user) { ?> <?=$user->name?> <?php } } ?> <?php if ($users): ?> <?php foreach ($users as $user): ?> <?=$user->name?> <?php endforeach ?> <?php endif ?>
  13. Never use curly brackets. <?php foreach ($users as $user) {

    ?> <?=$user->name?> <?php } ?> <?php foreach ($users as $user): ?> <?=$user->name?> <?php endforeach ?>
  14. <?php $this->layout('template', ['title' => 'User Profile']) ?> ! <h1>Hello <?=$this->e($name)?></h1>

    ! <h2>Friends</h2> <ul> <?php foreach($friends as $friend): ?> <li> <a href="/profile/<?=$this->e($friend->id)?>"> <?=$this->e($friend->name)?> </a> </li> <?php endforeach ?> </ul> ! <?php if ($invitations): ?> <h2>Invitations</h2> <p>You have some friend invites!</p> <?php endif ?>
  15. <div class="item" tal:repeat="value values"> <div class="title"> <span tal:condition="value/hasDate" tal:replace="value/getDate"/> <a

    tal:attributes="href value/getUrl" tal:content="value/getTitle"/> </div> <div id="content" tal:content="value/getContent"/> </div>
  16. 1. HTML escaping 2. HTML attribute escaping 3. CSS escaping

    4. JavaScript escaping 5. URL escaping Be aware of the different types of escaping:
  17. Without automatic escaping, you MUST manually escape every single variable.

    And you will probably forget once in a while!!!
  18. class Template { protected $values; ! public function __get($name) {

    return $this->escape( $this->values[$name] ); } }
  19. class Template { protected $values; ! public function __get($name) {

    return new TemplateProxy( $this->values[$name] ); } }
  20. class TemplateProxy { protected $value; ! public function __get($name) {

    return new TemplateProxy($this->name); } ! public function __call($name, $args) { return new TemplateProxy(...); } ! public function __toString() { return $this->escape($this->value); } }
  21. <ul> {% for item in items %} <li>{{ item }}</li>

    {% else %} <li>No items found.</li> {% endfor %} </ul>
  22. So what exactly is basic formatting then? • Date formatting

    • Case changes • String concatenation • String trimming • Number formatting • URL encoding
  23. namespace App\ViewModels; ! class UsersViewModel { public function users() {

    return [ ['name' => 'Jonathan'], ['name' => 'Amy'], ['name' => 'Joey'], ]; } }
  24. Rule #4: Controllers can instantiate only one object. Therefore, views

    can only know about one instance variable and views should only send messages to that object. — Sandi Metz, rules for developers
  25. {% include 'partials/header.html' with {'title': 'Home'} %} ! <p>Your page

    content.</p> ! {% include 'partials/footer.html' %}
  26. <select> <?php foreach ($users as $user): ?> <option <?php if

    ($current_user === $user) echo 'selected' ?> value="<?=$user->id?>"> <?=$user->name?> </option> <?php endforeach ?> </select>
  27. <select> <?php foreach ($users as $user): ?> <?php if ($current_user

    === $user): ?> <option selected value="<?=$user->id?>"><?=$user->name?></option> <?php else ?> <option value="<?=$user->id?>"><?=$user->name?></option> <?php endif ?> <?php endforeach ?> </select>
  28. template.html {% extends "template.html" %} ! {% block title %}Profile{%

    endblock %} {% block content %} <h1>Profile</h1> <p>Hello, {{ name }}</p> {% endblock %} profile.html <html> <head> <title> {% block title %} Default title {% endblock %} </title> </head> <body> ! <main> {% block content %} <p>Default content</p> {% endblock %} </main> ! </body> </html>