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

Stash: template inheritance

Stash: template inheritance

Presented to the Brighton EE meetup on 17th July 2015


Mark Croxton

July 17, 2015

More Decks by Mark Croxton

Other Decks in Programming


  1. Stas TEMPLATE INHERITANCE A THING BY Mark Croxton, Hallmark Design

  2. templat architectur

  3. Layout

  4. Layout Wrapper Base “wrapper” layout containing blocks and variables. Blocks

    & variables Define regions of the template that we can populate with content and optionally extend with custom layouts (partials). Blocks contain default markup and may be nested. wrapper block:body block:aside block:main
  5. Templat famil default_site blog.group _category.html _post.html index.html contact.group index.html site.group

    _page.html 404.html stash layouts base.html models post_model.html partials contact_form.html post_list.html post.html Children Parents
  6. Stas template Layouts Base “wrapper” templates, containing blocks and variables

    (“holes”) that can be filled (“extended”) by child templates. Partials Contain chunks of template code (html markup and tags) that can be used to fill the holes in the base template(s). Models Models represent a set of data that is used by multiple templates, such as a shared fieldgroup.
  7. Layout variables pg_title pg_subtitle pg_intro pg_copy pg_img pg_author pg_date pg_seo_title

    pg_seo_description pg_theme Custom fields cf_post_subtitle cf_post_intro cf_post_copy cf_post_img cf_product_intro cf_product_copy cf_product_img cf_service_copy cf_service_img Blocks block:main block:body block:aside Snippets sn_header sn_footer Low Variables lv_pagination lv_nav Nomenclatur Name for stuff
  8. <!DOCTYPE html> <html> {sn_head} <body> <header> <h1>{pg_title}</h1> <img src="{pg_img}" alt="">

    </header> <main> {exp:stash:block:main} {exp:stash:block:body} <p class="intro">{pg_intro}</p> {pg_copy} {/exp:stash:block:body} <aside> {exp:stash:block:aside} <h2>Blog categories</h2> {/exp:stash:block:aside} </aside> {/exp:stash:block:main} </main> {sn_footer} </body> </html> wrapper
  9. {stash:embed:layouts:base} {exp:channel:entries channel="blog" entry_id="{pg_entry_id}"} {exp:stash:set type="global"} {stash:pg_title}{title}{/stash:pg_title} {stash:pg_intro}{cf_blog_intro}{/stash:pg_intro} {stash:pg_copy}{cf_blog_copy}{/stash:pg_copy} {stash:pg_img}{cf_blog_img}{/stash:pg_img}

    {/exp:stash:set} {/exp:channel:entries} singl blo p
  10. {stash:embed:layouts:base} {exp:stash:extend name="block:body" with="partials:post_list" stash:channel="blog"} {exp:stash:set type="global"} {stash:pg_title}Latest blog posts{/stash:pg_title}

    {stash:pg_img}/images/blog_header.jpg{/stash:pg_img} {/exp:stash:set} lates blo p t
  11. <ul> {exp:channel:entries channel="{stash:channel}"} <li> <h2><a href="/blog/{url_title}">{title}</h2> <p>{cf_blog_intro}</p> <div class="meta"> Posted

    on {entry_date format="%F %d, %Y"} </div> </li> {/exp:channel:entries} </ul> p lis
  12. Model Models represent a common set of data that is

    shared and displayed by multiple templates. As a model’s data is intended to be reused in different views it doesn’t contain markup or display logic. Models keep you DRY (by removing boilerplate code), but increase complexity and interdependence (violating KISS). ”posts” fieldgroup blog entry page entry
  13. {exp:channel:entries channel="blog|page" entry_id="{pg_entry_id}"} {exp:stash:set type="global"} {stash:pg_title}{title}{/stash:pg_title} {stash:pg_intro}{cf_blog_intro}{/stash:pg_intro} {stash:pg_copy}{cf_blog_copy}{/stash:pg_copy} {stash:pg_img}{cf_blog_img}{/stash:pg_img} {/exp:stash:set}

    {/exp:channel:entries} p t mode
  14. {stash:embed:layouts:base} {!-- use the ‘posts’ model to capture data for

    this entry --} {stash:embed:models:posts process="start" parse="no"} {!-- load a custom layout for pages --} {exp:stash:extend name="block:body" with="partials:page"} singl pag
  15. resourc router

  16. 404 JSON Router Template path Channel entry API partial wrapper

    partial partials URI home partial partial models page post category
  17. Break out of traditional template_group/template routing Validate routes and set

    meta data for use in templates Remove conditional logic from templates Templates can assume a singular responsibility Catch incorrect and malicious URLs and 404 Inexpensive JSON/ HTML endpoints Resourc Router
  18. 'blog/:url_title' => function($router, $wildcard) { // valid blog post (channel

    2)? if ($wildcard->isValidUrlTitle(array('channel_id' => 2))) { // route to template $router->setTemplate('blog/_post'); // set {pg_entry_id} for use in template $router->setGlobal( 'pg_entry_id', $wildcard->getMeta('entry_id') ); } }, singl entr
  19. 'blog/category/:category_url_title(/P\d+)?' => function($router, $wildcard, $page="") { // valid blog category

    (in group 1)? if ($wildcard->isValidCategoryUrlTitle(array('group_id' => 1))){ // route to template $router->setTemplate('blog/_category'); // set {pg_title} and {pg_intro} for use in template $router->setGlobal( 'pg_title', $wildcard->getMeta('cat_name') ); $router->setGlobal( 'pg_intro', $wildcard->getMeta('cat_description') ); } }, categor listin
  20. // your rules here '.*' => function($router) { $router->set404(); },

  21. 'api/latest-posts' => function($router) { $now = ee()->localize->now; $query = ee()->db->select(

    'title, url_title, FROM_UNIXTIME(entry_date,"%d %M %Y") as date', FALSE ) ->where('status', 'open') ->where('channel_id', 2) ->where('entry_date <', $now) ->where('(expiration_date = 0 OR expiration_date > '.$now.')', NULL, FALSE) ->order_by('entry_date', 'DESC') ->limit(6) ->get('channel_titles'); $result = $query->result(); $router->json($result); }, endpoin
  22. stati cachin

  23. Ridiculously fast Bypasses EE and PHP entirely Granular cache-breaking with

    Mustash Can expire after a predetermined period of time & regenerate automatically Dynamic content can be loaded via ajax Works everywhere without complex configuration Easily move up to http proxy caching with Varnish and use the same cache-breaking rules Stati cachin
  24. {!-- use static caching for visitors only --} {exp:stash:static logged_out_only="yes"}

    {!-- static cache for one hour --} {exp:stash:static refresh="60"} {!-- apply HTML compression before caching --} {exp:stash:static compress="yes"} stati cachin
  25. <script id="tmpl-latest" type="text/html"> {{#latest.length}} <ul class="latest"> {{#latest}} <li><a href="/blog/{{url_title}}">{{title}}</a></li> {{/latest}}

    </ul> {{/latest.length}} </script> <script> $.Mustache.addFromDom(); $.getJSON('/api/latest-posts') .done( function(data) { $('#js-latest').mustache( 'tmpl-latest', { 'latest' : data } ); }); </script>
  26. github.co /cr to /Stas