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

Demystifying the Craft API for Twig Developers

Demystifying the Craft API for Twig Developers

Craft ships with a powerful and diverse API for doing all kinds of handy things. Helper functions, advanced database querying, input validators, content migrations, data caches, and much more. In this talk we will look at real world use cases to leverage the full suite of Craft features available to a Twig developer, as well as learn how to wade through the reference docs and discover more useful functionality on your own.

Originally presented at Dot All 2023.

Prateek Rungta

October 04, 2023
Tweet

More Decks by Prateek Rungta

Other Decks in Technology

Transcript

  1. API* Element Queries Twig Tags Twig Filters Twig Functions Cra

    Helpers Cra Components Yii Framework Composer Packages PHP
  2. <span class="text-xs {{ seatsAvailable < 10 ? 'text-red-500' }} {{

    seatsAvailable >= 10 and seatsAvailable <= 50 ? 'text- amber-500' }} {{ seatsAvailable > 50 ? 'text-green-500' }}"> {{ seatsAvailable }} seats </span>
  3. Using tag() {{ tag('span', { class: [ 'text-xs', seatsAvailable <

    10 ? 'text-red-500', seatsAvailable >= 10 and seatsAvailable <= 50 ? 't…', seatsAvailable > 50 ? 'text-green-500', ], text: seatsAvailable ~ ' seats', }) }}
  4. <span class="text-xs {{ seatsAvailable < 10 ? 'text-red-500' }} {{

    seatsAvailable >= 10 and seatsAvailable <= 50 ? 'text- amber-500' }} {{ seatsAvailable > 50 ? 'text-green-500' }}"> {{ seatsAvailable }} seats </span> {{ tag('span', { class: [ 'text-xs', seatsAvailable < 10 ? 'text-red-500', seatsAvailable >= 10 and seatsAvailable <= 50 ? 'text…', seatsAvailable > 50 ? 'text-green-500', ], text: seatsAvailable ~ ' seats', }) }} More Readable
  5. HTML A ributes as key-value pairs | attr({ … })

    attr({ … }) tag('a', { … }) ul(list, { … }) ol(list, { … }) input('tel', 'p', { … }) {% tag 'a' with { … } %}
  6. {% set eventsList = craft.entries .section('events') .orderBy('startDate') .all() %} {%

    set eventsList = craft.entries .section('events') .orderBy('startDate') .all() %}
  7. {% set eventsList = craft.entries .section('events') .all() |sort((a, b) =>

    a.startDate == b.startDate ? a.venue.one().title <=> b.venue.one().title : a.startDate <=> b.startDate ) %}
  8. {% set eventsList = craft.entries .section('events') .all() |sort((a, b) =>

    a.startDate == b.startDate ? a.venue.one().title <=> b.venue.one().title : a.startDate <=> b.startDate ) %}
  9. {% set eventsList = craft.entries .section('events') .all() |sort((a, b) =>

    a.startDate == b.startDate ? a.venue.one().title <=> b.venue.one().title : a.startDate <=> b.startDate ) %} {% set eventsList = craft.entries .section('events') .all() |multisort([ 'startDate', 'venue.0.title', ]) %} Less mental math
  10. {% macro truncate(string, chars = -1) %} {% set string

    = string | trim %} {% if truncate > 0 and string|length > truncate %} {% set string = string|slice(0, truncate) ~ '…' %} {% endif %} {{- string -}} {% endmacro %} ⚠ Bug: Partially Splits Words
  11. {% macro truncate(string, maxLength) %} {% set words = string|split('

    ') %} {% set truncatedString = '' %} {% for word in words %} {% set newString = truncatedString ~ ' ' ~ word %} {% if newString|length < maxLength %} {% set truncatedString = newString %} {% endif %} {% endfor %} {{ (truncatedString ~ '...')|trim }} {% endmacro %} ⚠ Bug: Can Skip Long Words
  12. {% macro truncate(content, words = 50, truncator = '...') %}

    {% set symbols = content | striptags | split(" ") %} {% set content = (symbols|length <= words) ? ( symbols | join(" ") | replace("\t", '') ) : ( symbols | slice(0, words) | join(" ") | replace("\t", '') ~ (truncator ? '&nbsp;' ~ truncator : '' ) ) %} {{ content|replace('&nbsp;', '') }} {% endmacro %} ⚠ Bug: Might double escape
  13. Use system lib :: Less custom logic Less mental math

    Fewer bugs Ship faster Widely deployed Future proof Less code More robust
  14. create() :: Cra & Yii Helpers Array Helper HTML Helper

    JSON Helper String Helper DateTime Helper URL Helper
  15. {% set response = create('GuzzleHttp\\Client') .get( 'https://en.wikipedia.org/api/rest…', { headers: {

    accept: 'application/json', charset: 'utf-8', }, }) %} {% if response.getStatusCode() == 200 %} {% set response = apiResponse .getBody() .getContents() | json_decode
  16. accept: 'application/json', charset: 'utf-8', }, }) %} {% if response.getStatusCode()

    == 200 %} {% set response = apiResponse .getBody() .getContents() | json_decode %} {{ response.description }} {{ response.extract_html }} {% endif %}
  17. {% set response = create('GuzzleHttp\\Client') .get( 'https://en.wikipedia.org/api/rest…', { headers: {

    accept: 'application/json', charset: 'utf-8', }, }) %} Immensely Powerful {% if response.getStatusCode() == 200 %} {% set response = apiResponse .getBody() .getContents() | json_decode %} {{ response.description }} {{ response.extract_html }} {% endif %}
  18. {# Store #} {% craft.app.cache.set(cacheKey, value) %} {# Re-use #}

    {% set value = craft.app.cache.get(cacheKey) %}
  19. {% set cacheKey = [url, params] %} {% set response

    = craft.app.cache.get(cacheKey) %} {% if response is same as(false) %} {# Make API call #} {% set response = ... %} {# Cache response #} {% do craft.app.cache.set(cacheKey, response) %} {% endif %}
  20. {% set eventsList = craft.entries .section('events') .orderBy('startDate') .all() %} {%

    for event in eventsList %} {{ event.title }} {{ event.artists.all()|join }} {{ event.venue.one() }} {{ event.ticketTypes.all()|join }} {% endfor %}
  21. {% set eventsList = craft.entries .section('events') .orderBy('startDate') .all() %} {%

    for event in eventsList %} {{ event.title }} {{ event.artists.all()|join }} {{ event.venue.one() }} {{ event.ticketTypes.all()|join }} {% endfor %}
  22. {% set eventsList = craft.entries .section('events') .orderBy('startDate') .with(['artists', 'venue', 'ticketTypes'])

    .all() %} {% for event in eventsList %} {{ event.title }} {{ event.artists.all()|join }} {{ event.venue.one() }} {{ event.ticketTypes.all()|join }} {% endfor %}
  23. {% set eventsList = craft.entries .section('events') .orderBy('startDate') .with(['artists', 'venue', 'ticketTypes'])

    .all() %} {% for event in eventsList %} {{ event.title }} {{ event.artists.all()|join }} {{ event.venue.one() }} {{ event.ticketTypes.all()|join }} {% endfor %} 3x(
  24. Recap Better readability Easier to maintain More future proof Fewer

    bugs Write lesser code Ship faster Improved performance Robustness Free system features “Superpowers”
  25. …not unique to the context of websites? • Math •

    Date & Time • Formatting • Encoding / decoding
  26. Tools for manipulating lists | map | filter | reduce

    | sort | multisort | column | unique
  27. Bunch of them take “arrow functions” |map(n => n *

    2) |filter(n => n > 20) |sort((a,b) => a<=>b)
  28. Why Better readability Easier to maintain More future proof Fewer

    bugs Write lesser code Ship faster Improved performance Robustness Free system features “Superpowers”
  29. When Ask yourself, is it: …common across other websites? …present

    in the Cra Control Panel? …not unique to the context of websites?
  30. As a tourist, mostly ge ing by using English &

    a translator app Navigating the way, visiting sites, taking in experiences
  31. However, a resident needs to pickup the local language Adopting

    local culture, making connections, feeling at home
  32. for loops & cra .entries # Haz API Tourist Resident

    Fear, Uncertainty, Doubt Discover, Try, Thrive