1

I am using a pattern library which expects a different data structure to what is in entry. Is there a way to parse the entry through a transformer class before the template is rendered?

Currently I have created a Twig function to run: {% set job = single(entry) %} which returns the mapped data for each different entry type.

I would like to hook into Craft to do this before the template is rendered and remove any mapping logic from the templates. Is this possible/practical?

  • Can you elaborate on your use case a bit as to what you're trying to do? – RitterKnight May 25 at 15:55
3

Definitely possible; you'd need to write a plugin or module in PHP to do it though. Probably it could listen to for the View::EVENT_BEGIN_PAGE event, and get the injected element via $element = Craft::$app->urlManager->getMatchedElement()

Something sorta like this:

use craft\web\View;

// ...

    $request = Craft::$app->getRequest();
    if ($request->getIsSiteRequest()) {
        // Handler: View::EVENT_BEGIN_PAGE
        Event::on(
            View::class,
            View::EVENT_BEGIN_PAGE,
            function () {
                Craft::debug(
                    'View::EVENT_BEGIN_PAGE',
                    __METHOD__
                );
                $element = Craft::$app->urlManager->getMatchedElement();
                if ($element !== null && ...) {
                    // ...do something
                }
            }
        );
    }

To make things clean, rather than modifying the element itself, I'd probably inject a new Twig variable, something like entryTransformed or something that your templating code could access.

| improve this answer | |
  • Ok thanks this seems like a good idea. What would be the best way to add the variable inside the callback? – Callum May 25 at 18:39
  • 1
    Yeah so the answer above isn't quite correct for what you're trying to do specifically. Check out my answer to that here: craftcms.stackexchange.com/questions/35427/… – andrew.welch May 26 at 18:37
2

What format are you trying to get your data into?

I can think of a few different ways to handle this depending on what you might want to do:

Element API

You don't mention what format you need but JSON is a popular format and the Element API is a first party solution in Craft.

Hidden Field

Another way to accomplish this would be to setup an Incognito field on your entry. Then, listen to the EVENT_BEFORE_SAVE_ELEMENT event using a plugin to transform your data and save it to the format you need. This is similar to how you're doing it in Twig now, except just in a different "place" in the request.

This also has the advantage of doing the data transform once when the entry is saved (instead of every page load or messing around with {% cache %} tags). Then you just grab it in Twig like any other field, similar to how you're doing it now.

Twig Filter

You mentioned this in your question. Since we don't have access to your Twig template, it's hard to know what you're trying to accomplish but I don't necessarily see a downside to doing it this way if your page performance is good. The only thing you might want to consider is adding {% cache %} tags around your output to give your server a break in that respect.

Page Injection

See Andrew's answer if you need to do things even "higher up" before the template layer.

| improve this answer | |
  • Thanks for the feedback. I ended up going with Andrew's answer. Do you know a good method of adding a variable to the template context in the event in his example? – Callum May 25 at 22:02
  • 1
    That's a good question, you might get more action if you ask it as a new question but one way to do it would be to create a Twig extension. – RitterKnight May 26 at 15:19

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.