Context in Statamic Tags
In our last post we discussed creating custom Tags in Statamic. One of the aspects of Tags that we will explore further is Context.
The documentation page (linked above) describes context as “is the array of values being used for rendering the template where your tag happens to be placed.” This effectively means, these are the variables available from the current iteration of the tag. In the case of our “blog” example, the variables consist of the fields on that particular entry.
This is where the “context” comes in - when we are inside a tag in our Antlers template, we have a new context. So, where we may be in a page template, the “title” is mapped to the page title; but if in the same template we iterate over blog posts from our “blog” tag, then the context changes, and we get the title of the blog entry.
<!-- page template -->
<h1>{{ title }}</h1>
{{ blog }} <!-- sets up a new context -->
<h2>{{ title }}</h2> <!--The title of the entry in the loop.-->
{{ /blog }}
Entry context
When the returned data in an entry of a collection, we get a bunch of the context for free from Statamic. Each entry will automatically have a “title” and a “slug,” and more, like date variables, depending on whether the collection is dated.
Otherwise, we get access to all of the fields that are connected to the particular entry. In my blog collection, each entry has an image field to display both on my index view, and my single entry view, using its field handle, which in thus case is simply “image.” In both templates, I can reference the image tag via its handle:
<!-- image tag -->
{{ blog }}
<img src="{{ image:url }}" alt="{{ image:alt }}">
<!-- or -->
{{ image }}
<img src="{{ url }}" alt="{{ alt }}">
{{/image }}
{{ /blog }}
We can make this one even more powerful using glide, but that will be the subject of a future post. For now, we can observe that the image field is an object with multiple properties, like “src” and “alt” the prefix “image” just needs to correspond to the name of the field, as mentioned above.
Custom context data
What if we wanted to programmatically make some custom data available as a tag? Let’s say we were lazy, and didn’t want to upload an image every time we create a new blog post; instead, for the sake of illustration, we might randomly fetch an image from an API and use that instead.
First, let’s make a Cats tag to do this for us:
php please make:Tag Cats
Then, in the index method we can fetch a random cat image, and return the data as an array. Our Tags/Cats.php
would look something like this:
namespace App\Tags;
use Statamic\Tags\Tags;
class Cats extends Tags
{
/**
* The {{ cats }} tag.
*
* @return string|array
*/
public function index()
{
$cat_json = file_get_contents('https://api.thecatapi.com/v1/images/search');
$cat_data = json_decode($cat_json, true);
$cat_img = $cat_data[0];
return [
'url' => $cat_img['url'],
'id' => $cat_img['id']
];
}
}
For now, let’s pretend the above index
function has the proper error handling and checking, and we’ll imagine it just works. All the time. And feel free to use Guzzle or whatever http request library works for you.
In our Antlers template, the items in the returned array are the the new variables in the context of our “cats” tag:
{{ cats }}
<img src="{{ url }}" id="{{ id }}" />
{{ /cats }}
Just like our “image” example above, we can reference the “url” and “id” values in the context of our “cats” tag.
Final Context
While this example might be trivial, it illustrates how we can write some potentially complex logic, and return simple values to our template in the form of contextual variables. Our tags get their context variables from explicitly returning an array, or from the fields that are attached to a Statamic entry.
Consider the WordPress ACF style to get some data in your template:
<?php $some_field = get_field('my_field'); ?>
<p><?php echo $some_field; ?></p>
By contrast, here’s the Antlers equivalent context data:
<p>{{ some_field }}</p>
Which would you choose? To me, it’s a no-brainer.