Dot All Lisbon – the official Craft CMS conference – is happening September 23 - 25.

Functions

The following functions are available to Twig templates in Craft:

Function | Description -------- | ----------- actionInput | Outputs a hidden action input. actionUrl | Generates a controller action URL. alias | Parses a string as an alias. attr | Generates HTML attributes. attribute | Accesses a dynamic attribute of a variable. beginBody | Outputs scripts and styles that were registered for the “begin body” position. block | Prints a block’s output. canCreateDrafts
canDelete
canDeleteForSite
canDuplicate
canSave
canView | Check permissions for a given element. ceil | Rounds a number up. className | Returns the fully qualified class name of a given object. clone | Clones an object. collect | Returns a new collection. combine | Combines two arrays into one. configure | Sets attributes on the passed object. constant | Returns the constant value for a given string. cpUrl | Generates a control panel URL. create | Creates a new object. csrfInput | Returns a hidden CSRF token input. cycle | Cycles on an array of values. dataUrl | Outputs an asset or file as a base64-encoded data URL. date | Creates a date. dump | Dumps information about a variable. encodeUrl | Encodes and unencoded components of a URL. endBody | Outputs scripts and styles that were registered for the “end body” position. entryType | Gets an entry type definition by its handle. expression | Creates a database expression object. failMessageInput | Outputs a hidden failMessage input. fieldValueSql | Generates an SQL expression for accessing specific fields in elements’ JSON content column. floor | Rounds a number down. getenv | Returns the value of an environment variable. gql | Executes a GraphQL query against the full schema. head | Outputs scripts and styles that were registered for the “head” position. hiddenInput | Outputs a hidden input. include | Returns the rendered content of a template. input | Outputs an HTML input. max | Returns the biggest value in an array. min | Returns the lowest value in an array. ol | Outputs an array of items as an ordered list. parent | Returns the parent block’s output. parseBooleanEnv | Parses a string as an environment variable or alias having a boolean value. parseEnv | Parses a string as an environment variable or alias. plugin | Returns a plugin instance by its handle. random | Returns a random value. range | Returns a list containing an arithmetic progression of integers. raw | Wraps the given string in a Twig\Markup object to prevent it from getting HTML-encoded when output. redirectInput | Outputs a hidden redirect input. renderObjectTemplate | Renders an object template. seq | Outputs the next or current number in a sequence. shuffle | Randomizes the order of the items in an array. siteUrl | Generates a front-end URL. source | Returns the content of a template without rendering it. successMessageInput | Outputs a hidden successMessage input. svg | Outputs an SVG document. tag | Outputs an HTML tag. template_from_string | Loads a template from a string. ul | Outputs an array of items as an unordered list. url | Generates a URL.

actionInput

A shortcut for outputting a hidden input used to route a POST request to a particular controller action. This is effectively the same as writing <input type="hidden" name="action" value="controller/action/route"> directly into a template.

{{ actionInput('users/save-user') }}

You can optionally set additional attributes on the tag by passing an options argument.

{{ actionInput('users/save-user', {
  id: 'action-input'
}) }}

actionUrl

Returns a controller action URL, automatically accounting for relative vs. absolute format and the active config5:actionTrigger setting.

Arguments

The actionUrl() function has the following arguments:

  • path – The path that the resulting URL should point to on your site. It will be appended to your base site URL.
  • params – Any query string parameters that should be appended to the URL. This can be either a string (e.g. 'foo=1&bar=2') or a hash (e.g. { foo: '1', bar: '2' }).
  • scheme – Which scheme the URL should use ('http' or 'https'). The default value depends on whether the current request is served over SSL or not. If not, then the scheme in your Site URL will be used; if so, then https will be used.

alias

Passes a string through Craft::getAlias(), which will check if the string begins with an alias. (See Configuration for more info.)

attr

Generates a list of HTML attributes based on the given hash, using yii2:yii\helpers\BaseHtml::renderTagAttributes().

{% set myAttributes = {
  class: ['one', 'two'],
  disabled: true,
  readonly: false,
  data: {
    baz: 'Escape this "',
    qux: {
      some: ['data', '"quoted"']
    }
  },
  style: {
    'background-color': 'red',
    'font-size': '20px'
  },
} %}

Attribute values are HTML-encoded automatically:

{# Output: <div title="Greetings &amp; Salutations"> #}

beginBody

Outputs any scripts and styles that were registered for the “begin body” position. It should be placed right after your <body> tag.

  {{ beginBody() }}

  <h1>{{ page.name }}</h1>
  {{ page.body }}

block

Prints a block’s output.

This works identically to Twig’s core block function.

canCreateDrafts

Checks whether the current user (or a specific user, when provided) can create drafts from the passed element.

{% if canCreateDrafts(entry) %}
  <a href="{{ entry.getCpEditUrl() }}">Edit</a>
{% endif %}

canDelete

Checks whether the current user (or a specific user, when provided) can delete the passed element.

{% if canDelete(entry) %}
  <a href="{{ entry.getCpEditUrl() }}">Edit</a>
{% endif %}

canDeleteForSite

Checks whether the current user (or a specific user, when provided) can delete the passed element from the site it was loaded in.

{% if canDeleteForSite(entry) %}
  <a href="{{ entry.getCpEditUrl() }}">Edit</a>
{% endif %}

canDuplicate

Checks whether the current user (or a specific user, when provided) can duplicate the passed element.

{% if canDuplicate(entry) %}
  <a href="{{ entry.getCpEditUrl() }}">Edit</a>
{% endif %}

canSave

Checks whether the current user (or a specific user, when provided) can save the passed element.

{% if canSave(entry) %}
  <a href="{{ entry.getCpEditUrl() }}">Edit</a>
{% endif %}

canView

Checks whether the current user (or a specific user, when provided) can view the passed element within the control panel.

{% if canView(entry) %}
  <a href="{{ entry.getCpEditUrl() }}">Edit</a>
{% endif %}

ceil

Rounds a number up.

{{ ceil(42.1) }}
{# Output: 43 #}

className

Returns the fully qualified class name of a given object.

{% set class = className(entry) %}
{# Result: 'craft\\elements\\Entry' #}

clone

Clones a given object.

{% set query = craft.entries().section('news') %}
{% set articles = clone(query).type('articles') %}

collect

Returns a new collection.

{% set collection = collect(['a', 'b', 'c']) %}

combine

Combines two arrays into one, using the first array to define the keys, and the second array to define the values.

{% set arr1 = ['a', 'b', 'c'] %}
{% set arr2 = ['foo', 'bar', 'baz'] %}
{% set arr3 = combine(arr1, arr2) %}
{# arr3 will now be `{a: 'foo', b: 'bar', c: 'baz'}` #}

configure

Passes through the behavior of the Craft::configure() method inherited from Yii::configure(). It’s similar to create in that it applies attributes to an object, but instead of creating new instances it accepts an existing object and modifies it.

{# Modify an `EntryQuery` object set up by a relational field: #}
{% set myRelatedEntries = configure(entry.myEntriesField, {
  section: 'blog'
}).all() %}

configure() can be used to set a model or element’s attributes—but we don’t generally recommend this, as templates are intended to present content rather than modify it:

{% do configure(entry, { title: 'New Title' }) %}
{% do craft.app.elements.saveElement(entry) %}

constant

Returns the constant value for a given string.

This works identically to Twig’s core constant function.

cpUrl

Returns a control panel URL, automatically accounting for relative vs. absolute format and the active config5:cpTrigger setting.

Arguments

The cpUrl() function has the following arguments:

  • path – The path that the resulting URL should point to on your site. It will be appended to your base site URL.
  • params – Any query string parameters that should be appended to the URL. This can be either a string (e.g. 'foo=1&bar=2') or a hash (e.g. {foo:'1', bar:'2'}).
  • scheme – Which scheme the URL should use ('http' or 'https'). The default value depends on whether the current request is served over SSL or not. If not, then the scheme in your Site URL will be used; if so, then https will be used.

create

Creates a new object instance based on a given class name or object configuration. See yii2:Yii::createObject() for a full explanation of supported arguments.

{# Pass in a class name #}
{% set cookie = create('yii\\web\\Cookie') %}

{# Or a full object configuration hash #}
{% set cookie = create({
  class: 'yii\\web\\cookie',
  name: 'foo',
  value: 'bar'
}) %}

csrfInput

Renders a CSRF token input element for use in an HTML form. All sites that have CSRF protection enabled must include this in each form that makes a POST request.

{{ csrfInput() }}

You can set additional attributes on the rendered tag by passing an options argument:

{{ csrfInput({
  id: 'my-csrf-input',
}) }}

The output of csrfInput() should not be cached—statically, or using template caches.

Craft automatically sends no-cache headers when generating or outputting a CSRF token. <Since ver="5.3.0" description="We began sending automatic no-cache headers in {product} {ver}." />

A special async key in the passed hash allows you to override the global config5:asyncCsrfInputs setting for a single input <Since ver="5.1.0" feature="The asyncCsrfInputs setting" />:

{{ csrfInput({
  async: true,
}) }}

Asynchronous CSRF inputs are cacheable, and therefore no headers are sent—but other features of the page (including other csrfInput() calls) can still cause no-cache headers to be sent.

Craft outputs a placeholder element, and registers a snippet of JavaScript that requests a token over Ajax, once the page has loaded in the client. Only one request is made, regardless of the number of inputs on the page.

dataUrl

Outputs an asset or file as a base64-encoded data URL. You can pass it an craft5:craft\elements\Asset object or a file path (optionally using an alias).

{# Asset object `myLogoAsset` #}

{# File path, optionally using an alias #}

{# Output: <img src="data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjEwMCIgdmd(...)" /> #}

The dataUrl() function has the following arguments:

  • file - The asset or path to a file to be encoded.
  • mimeType - Optional MIME type. If omitted, the file’s MIME type will be determined automatically.

date

Converts an argument to a date to allow comparison, like Twig’s date() function.

The argument can be one of PHP’s supported date and time formats, or additionally a date/time array.

{% if date(asset.dateModified) < date('-2days') %}
  {# asset is not new #}
{% endif %}

A null or empty argument defaults to the current date:

{% if date() > date('2021/06/01') %}
  {# today is past June 1, 2021 #}
{% endif %}

Craft additionally supports passing a date/time array:

{% set myDate = {
  date: '2021-01-15',
  timezone: 'America/Los_Angeles',
  time: '10:57',
} %}

{% if now > date(myDate) %}
  {# today is past January 15, 2021 #}
{% endif %}

dump

Overrides Twig’s default dump() function with one that is available in all contexts (not just when the Twig environment is in “debug” mode), and produces consistent output with the {% dd %} tag.

{% set news = craft.entries()
  .section('news')
  .all() %}

{{ dump(news|column('title')) }}

encodeUrl

Ensures a URL contains only ASCII characters. The underlying craft5:craft\helpers\UrlHelper::encodeUrl() function is automatically called by Craft’s internal redirection logic. This is typically only required when using a URL in an HTTP header. Supposing we have a URL with accented characters like https://my-project.ddev.site/pages/åbçdé

{# …unencoded output leads to garbled characters, and won’t resolve if requested: #}
{% header "X-See-Also: #{entry.url}" %}
{# -> https://my-project.ddev.site/åbçdé  #}

{# …but encoding the output preserves the original accented characters: #}
{% header "X-See-Also: #{encodeUrl(entry.url)}" %}
{# -> https://my-project.ddev.site/%C3%A5b%C3%A7d%C3%A9 #}

endBody

Outputs any scripts and styles that were registered for the “end body” position. It should be placed right before your </body> tag.

  <head>
    {# ... #}
  </head>
  <body>
    <h1>{{ page.name }}</h1>
    {{ page.body }}

    {{ endBody() }}
  </body>

entryType

Get a reference to an entry type, by its handle:

{% set type = entryType('post') %}

{{ type.name }}

This is equivalent to using the entries service, directly:

{% set type = craft.app.entries.getEntryTypeByHandle('post') %}

{{ type.name }}

When creating entries in a front-end form, you can use the entryType() function to find the correct ID to submit (IDs can be unstable between environments, due to the way project config works):

  {{ csrfInput() }}
  {{ actionInput('entries/save-entry') }}

  {{ hiddenInput('typeId', entryType('post').id) }}

  {# ... #}

expression

Creates and returns a new yii2:yii\db\Expression object, for use in database queries.

{% set entries = craft.entries()
  .andWhere(expression('[[authorId]] = :authorId', {authorId: currentUser.id}))
  .all() %}

failMessageInput

Renders a hidden input element with a tamper-proof failure message.

  {{ actionInput('users/save-user') }}
  {{ failMessageInput('Something went wrong when updating your profile.') }}

  {# ... #}

You can set additional attributes on the input tag by passing an options argument:

{{ failMessageInput('Something went wrong when updating your profile.', {
  id: 'failure-message-input'
}) }}

The output is equivalent to this Twig:

  type="hidden"
  name="failMessage"
  value="{{ 'Something went wrong when updating your profile.'|hash }}">

Failure messages are stored in the session as flashes.

fieldValueSql

Generates a platform-specific SQL expression to extract a value from elements’ JSON content column.

{% set longestFilm = craft.entries()
  .section('films')
  .max(fieldValueSql(entryType('film'), 'runtimeMinutes')) %}

Craft automatically handles this for orderBy() and select() expressions, as well as when using field methods, directly:

{% set shortFilms = craft.entries()
  .section('films')
  .runtimeMinutes('<= 20')
  .orderBy('runtimeMinutes DESC')
  .all() %}

Arguments

  • provider — An object that implements craft\base\FieldLayoutProviderInterface, like an entry type or asset volume—basically anything that defines a field layout.

    {# Load a field layout provider: #}
    {# set volume = craft.app.volumes.getVolumeByHandle('photos') %}
    {% set longExposures = craft.assets()
      .volume('photos')
      .andWhere('between', (fieldValueSql(volume, 'shutterSpeed')), 0.17, 1)
      .all() %}
    

    The provider can also be passed from an existing resource, like entry.type.

  • fieldHandle — The field’s handle in the given field layout. This may be different than the field’s global definition—especially if the field is present multiple times in the layout.

floor

Rounds a number down.

{{ floor(42.9) }}
{# Output: 42 #}

getenv

Returns the value of an environment variable, using craft5:craft\helpers\App::env().

{{ getenv('MAPS_API_KEY') }}

Take care to not leak sensitive environment variables into your HTML!

gql

Executes a GraphQL query against the full schema.

{% set result = gql('{
  entries (section: "news", limit: 2, orderBy: "dateCreated DESC") {
    postDate @formatDateTime (format: "Y-m-d")
    title
    url
    ... on news_article_Entry {
      shortDescription
      featuredImage {
        url @transform (width: 300)
        altText
      }
    }
  }
}') %}

{% for entry in result.data %}
  <h3><a href="{{ entry.url }}">{{ entry.title }}</a></h3>
  <p class="timestamp">{{ entry.postDate }}</p>

  {% set image = entry.featuredImage[0] %}
  <img class="thumb" src="{{ image.url }}" alt="{{ image.altText }}">

  {{ entry.shortDescription|markdown }}
  <p><a href="{{ entry.url }}">Continue reading…</a></p>
{% endfor %}

head

Outputs any scripts and styles that were registered for the “head” position. It should be placed right before your </head> tag.

  <title>{{ siteName }}</title>
  {{ head() }}

hiddenInput

Generates an HTML input tag.

{{ hiddenInput('entryId', entry.id) }}
{# Output: <input type="hidden" name="entryId" value="100"> #}

You can optionally set additional attributes on the tag by passing an options argument.

{{ hiddenInput('entryId', entry.id, {
  id: 'entry-id-input'
}) }}

include

Returns the rendered content of a template.

This works identically to Twig’s core include function.

input

Generates an HTML input tag.

{{ input('email', 'email-input', '') }}
{# Output: <input type="email" name="email-input" value=""> #}

You can optionally set additional attributes on the tag by passing an options argument.

{{ input('email', 'email-input', '', {
  id: 'custom-input'
}) }}
{# Output: <input type="email" id="custom-input" name="email-input" value=""> #}

max

Returns the biggest value in an array.

This works identically to Twig’s core max function.

min

Returns the lowest value in an array.

This works identically to Twig’s core min function.

ol

Outputs an array of items as an ordered list.

{% set titles = craft.entries()
  .section('news')
  .select('title')
  .column() %}
{{ ol(titles) }}
{# Output:
  <li>Shocking Foo</li>
  <li>You Won’t Believe This Bar</li>
  <li>Ten Baz You Can’t Live Without</li>
#}

Arguments

The ol() function has the following arguments:

  • items – An array of items to be wrapped in <li>s. These will be HTML-encoded by default.
  • params – An attributes argument where each key+value will be set as attributes on the <ol>, with the exception of two special options:
    • encode: false – Prevents the list items from being HTML-encoded.
    • itemOptions: {...} – Tag attributes to be applied to each of the <li>s.

parseBooleanEnv

Checks if a string references an environment variable ($VARIABLE_NAME) and returns the referenced boolean value, or null if a boolean value can’t be determined.

parseEnv

Checks if a string references an environment variable ($VARIABLE_NAME) and/or an alias (@aliasName), and returns the referenced value.

If the string references an environment variable with a value of true or false, a boolean value will be returned.

plugin

Returns a plugin instance by its handle, or null if no plugin is installed and enabled with that handle.

{{ plugin('commerce').version }}

raw

Wraps the given string in a Twig\Markup object to prevent it from getting HTML-encoded when output.

{% set html = raw('<p>Don’t encode me.</p>') %}
{{ html }}

This works similarly to the raw filter, except that Twig will remember not to escape the HTML even if the variable is passed to another template/macro, whereas |raw filters only have an effect if used directly in an output tag.

redirectInput

Output an HTML input equivalent to <input type="hidden" name="redirect" value="{{ url|hash }}">, for use in forms that POST data to Craft or a plugin.

{{ redirectInput(url) }}

The URL is typically parsed as an object template, meaning dynamic redirects are possible, based on the data being manipulated.

You can optionally set additional attributes on the resulting input tag by passing an options argument:

{{ redirectInput(url, {
  id: 'redirect-input'
}) }}

Don’t include user-provided data in redirection URLs, directly (via interpolation in a template) or indirectly (rendered in an object template).

renderObjectTemplate

Evaluates a string as an object template, using the provided element, model, or hash.

{{ renderObjectTemplate('👋 Hi, {fullName}!', currentUser) }}
{# Output: 👋 Hi, Oli! #}

{{ renderObjectTemplate('✨ {foo}', { foo: "I’m a made-up hash!" }) }}
{# Output: ✨ I’m a made-up hash! #}

Do not pass user-supplied templates to the renderObjectTemplate() function!

seq

Outputs the next or current number in a sequence, defined by name:

Each time the function is called, the given sequence will be automatically incremented.

You can optionally have the number be zero-padded to a certain length.

{{ now|date('Y') ~ '-' ~ seq('orderNumber:' ~ now|date('Y'), 5) }}
{# Output: 2018-00001 #}

To view the current number in the sequence without incrementing it, set the next argument to false.

shuffle

Randomizes the order of the elements within an array.

{% set promos = craft.entries().section('promos').all() %}
{% set shuffledPromos = shuffle(promos) %}

{% for promo in shuffledPromos %}
  <div class="promo {{ promo.slug }}">
    <h3>{{ promo.title }}</h3>
    <p>{{ promo.description }}</p>
    <a class="cta" href="{{ promo.ctaUrl }}">{{ promo.ctaLabel }}</a>
  </div>
{% endfor %}

siteUrl

Similar to url(), except only for creating URLs to pages on your site.

Arguments

The siteUrl() function has the following arguments:

  • path – The path that the resulting URL should point to on your site. It will be appended to your base site URL.
  • params – Any query string parameters that should be appended to the URL. This can be either a string (e.g. 'foo=1&bar=2') or a hash (e.g. {foo:'1', bar:'2'}).
  • scheme – Which scheme the URL should use ('http' or 'https'). The default value depends on whether the current request is served over SSL or not. If not, then the scheme in your Site URL will be used; if so, then https will be used.
  • siteId – The ID of the site that the URL should point to. By default the current site will be used.

source

Returns the content of a template without rendering it.

This works identically to Twig’s core source function.

successMessageInput

Renders a hidden input element with a tamper-proof success message.

  {{ actionInput('users/save-user') }}
  {{ successMessageInput('Your profile has been updated!') }}

  {# ... #}

You can set additional attributes on the input tag by passing an options argument:

{{ successMessageInput('Your profile has been updated!', {
  id: 'success-message-input'
}) }}

The output is equivalent to this Twig:

  type="hidden"
  name="successMessage"
  value="{{ 'Your profile has been updated!'|hash }}">

Success messages are stored in the session as flashes.

svg

Outputs an SVG document.

You can pass the following things into it:

  • An SVG file path.

    {{ svg('@webroot/icons/lemon.svg') }}
    
  • A craft5:craft\elements\Asset object, such as one pulled in from an Assets field.

    {% set image = entry.myAssetsField.one() %}
    {% if image and image.extension == 'svg' %}
      {{ svg(image) }}
    {% endif %}
    
  • Raw SVG markup.

    {% set image = include('_includes/icons/lemon.svg') %}
    {{ svg(image) }}
    

By default, if you pass an asset or raw markup into the function, the SVG will be sanitized of potentially malicious scripts using svg-sanitizer, and any IDs or class names within the document will be namespaced so they don’t conflict with other IDs or class names in the DOM. You can disable those behaviors using the sanitize and namespace arguments:

{{ svg(image, sanitize=false, namespace=false) }}

Images passed via path/alias will not automatically be sanitized and namespaced.

You can also specify a custom class name that should be added to the root <svg> node using the attr filter:

{{ svg('@webroot/icons/lemon.svg')|attr({ class: 'lemon-icon' }) }}

Consider caching the output, especially if you’re loading SVG files from a remote volume, so Craft doesn’t download the file each time your template is rendered.

tag

Renders a complete HTML tag.

{{ tag('div', {
  class: 'foo'
}) }}
{# Output: <div class="foo"></div> #}

If text is included in the attributes argument, its value will be HTML-encoded and set as the text contents of the tag.

{{ tag('div', {
  text: 'Hello'
}) }}
{# Output: <div>Hello</div> #}

If html is included in the attributes argument (and text isn’t), its value will be set as the inner HTML of the tag (without getting HTML-encoded).

Be sure you trust any input you provide via html since it could be an XSS (cross-site scripting) attack vector. It’s safer to use text wherever possible.

{{ tag('div', {
  html: 'Hello<br>world'
}) }}
{# Output: <div>Hello<br>world</div> #}

All other keys passed to the second argument will be set as attributes on the tag, using yii2:yii\helpers\BaseHtml::renderTagAttributes().

If an attribute is set to true, it will be added without a value.

{{ tag('input', {
  id: 'foo',
  name: 'bar',
  required: true
}) }}
{# Output: <input id="foo" name="bar" required> #}

Any attribute set to null or false will be omitted.

Attribute values are HTML-encoded automatically:

{{ tag('input', {
  name: 'bar',
  value: 'Foobar & Baz',
}) }}
{# Output: <input name="bar" value="Foobar &amp; Baz"> #}

ul

Outputs an array of items as an unordered list.

{% set titles = craft.entries()
  .section('news')
  .select('title')
  .column() %}
{{ ul(titles) }}
{# Output:
  <li>Shocking Foo</li>
  <li>You Won’t Believe This Bar</li>
  <li>Ten Baz You Can’t Live Without</li>
#}

Arguments

The ul() function has the following arguments:

  • items – An array of items to be wrapped in <li>s. These will be HTML-encoded by default.
  • params – An attributes argument where each key+value will be set as attributes on the <ul>, with the exception of two special options:
    • encode: false – Prevents the list items from being HTML-encoded.
    • itemOptions: {...} – Tag attributes to be applied to each of the <li>s.

url

Returns a URL.

Arguments

The url() function has the following arguments:

  • path – The path that the resulting URL should point to on your site. It will be appended to your base site URL.
  • params – Any query string parameters that should be appended to the URL. This can be either a string (e.g. 'foo=1&bar=2') or a hash (e.g. {foo:'1', bar:'2'}).
  • scheme – Which scheme the URL should use ('http' or 'https'). The default value depends on whether the current request is served over SSL or not. If not, then the scheme in your Site URL will be used; if so, then https will be used.
  • mustShowScriptName – If this is set to true, then the URL returned will include “index.php”, disregarding the config5:omitScriptNameInUrls config setting. (This can be useful if the URL will be used by POST requests over Ajax, where the URL will not be shown in the browser’s address bar, and you want to avoid a possible collision with your site’s .htaccess file redirect.)

Using the url() function has advantages over hard-coding URLs in your templates:

  • Generated URLs will encourage consistency by respecting settings like addTrailingSlashesToUrls.
  • Your site will be more portable, making it easier to do something like move to a new domain or subdomain.
  • If the page has a token URL parameter, that token will automatically get appended to generated URLs to maintain preview context navigating around the site.

You can use the url() function for appending query string parameters and/or enforcing a scheme on an absolute URL:

{{ url('http://my-project.tld', 'foo=1', 'https') }}
{# Output: "https://my-project.tld?foo=1" #}