2

If I am visiting /recipes/spaghetti which corresponds to an entry in a recipes entry type and the recipes/entry template, is there a way to directly get the current entry's data from within the template? Here's what I have, and it works, but I feel like there might be a better way. Basically, since the entry is already associated to the route, I'm wondering if there is a shortcut to access the entry's data.

{% set uri = craft.app.request.fullUri %}
{% set recipe = craft.entries().type('recipes').uri(uri).one() %}
6
  • What does this Entry's Section settings look like? Craft should be automatically generating URIs and mapping them to a template based on that config—no need to look them up manually, unless you're trying to access them outside that scheme. In short, you may already have access to entry in this context! Oct 24, 2021 at 0:10
  • The uri is mapped to a template - I get that part. I want to be able to access the field data from the entry - that's what the queries I set up do. I am just wondering if there is a less roundabout way of getting that data. Oct 24, 2021 at 1:44
  • Ok, perfect! You don’t need to do the lookup manually—Craft injects the current Entry/Element as entry in your template, along with all the field data you’d expect. 👍 Oct 24, 2021 at 2:41
  • 1
    Oh, wonderful! It works for me, but strangely doesn't seem to be documented on the Entries page: craftcms.com/docs/3.x/entries.html. Could you add an answer with that info, along with a link to documentation if there is one? Oct 24, 2021 at 3:44
  • 1
    Just made a PR to the docs, so hopefully that will be changed soon. Oct 24, 2021 at 4:07

1 Answer 1

4

Surprisingly, the Craft docs aren't super clear on this so I'll post a little info.

When you set up a Section in the Control Panel, you set the URI Format and Template fields to map to an entry template.

When you hit a route that matches that URI Format, Craft queries for the entry that matches the route, then it automagically injects a Twig variable named entry into that template for you. (If it doesn't find one, it throws a 404 Not Found exception.)

The same is true for Categories. You can set up a Category with a URI Format and Template to map to a category template. In those templates you'll have a Twig variable named category.

Sometimes, however, you might find yourself in an unfortunate situation where an included/embedded template or a macro doesn't have the current entry variable in its context. In that case, you can do something like this:

{% set entry = craft.app.getUrlManager().getMatchedElement() %}

See this answer for caveats: How can I get the requested entry from a plugin?

These three blocks of code should render the same thing:

{# This is the way #}
<h1>{{ entry.title }}<h1>
{# This makes an extra database query #}
{% set uri = craft.app.request.fullUri %}
{% set recipe = craft.entries().type('recipes').uri(uri).one() %}
<h1>{{ recipe.title }}</h1>
{# Only if you need to. Doesn't make an extra database query #}
{% set recipe = craft.app.getUrlManager().getMatchedElement() %}
<h1>{{ recipe.title }}</h1>

I hope that helps!

Edit:

Can routes collide?

Craft will not let you save an element with a duplicate slug, so for Element routes, there can only be one ⚔️

You can, however, define custom routes in places like the /config/routes.php file or in the Control Panel under Settings -> Routes that might match an Element route. In that case, the Element Route wins.

The Craft docs show the order of precedence: https://craftcms.com/docs/3.x/routing.html

2
  • Thanks Sam for the helpful info...followup question, and if you know the answer, maybe you can expand your answer - What happens if two entries match a uri route? Which gets injected into the entry variable? I don't know of many good use cases for this, but it seems that it is quite possible thanks to the flexibility of craft, and it's conceivable it could be useful if the behavior is predictable. Oct 26, 2021 at 18:33
  • 1
    ah, that's a good observation. Will update. Oct 27, 2021 at 22:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.