2

Note: this question pertains to Craft 2 Pro. Craft 3 is not currently an option.

What I need to do

I have some stand-alone utilities that don't need to exist within the Craft framework, so I would really rather not have to go down the road of learning how to develop Craft extensions.

The trick is that these stand-alone utilities do their thing, and then redirect the user to various Craft entries, and I need some way to send arbitrary status messages from the standalone utilities that can then be displayed by the Craft templates.

Example Scenario

We are using a external utility for online fundraising. The user starts on a page that exists as a Craft entry ('Donate'), proceeds to the external utility's web space, and is sent back to the Craft site.

If something goes wrong in the transaction, I need to be able to display any number of error messages to the user, on the original Craft entry, allowing the user to try the donation again. I don't want to create multiple copies of the original Craft entry, one for each possible error message. That seems like an unreasonable duplication of effort and data, and a nightmare in the making if any changes need to be made to what the user sees.

What I hoped would be possible

The external utilities exist on the same domain, so I hoped I might be able to use PHP's $_SESSION variable to set the status message, and then have the Twig template display the message.

Based on what I found, it seems that Twig (at least in Craft 2) doesn't have access to $_SESSION without editing the Craft application code to create a new global variable corresponding to $_SESSION. I want to avoid editing Craft application code to ensure that nothing gets clobbered by updates to Craft.

What to do?

How can I send arbitrary external messages to a Craft entry so that they can be displayed by the Twig template? I don't think I know Craft well enough to know all the possibilities, and so I am not even sure how to search well for what other people have done.

I hope that writing my own extension isn't the answer to this because I haven't figured out how to do that, yet!

Update!

I went ahead with what was recommended in the "accepted answer" below, and it has worked. Here are the steps that I took:

  1. Add a custom route in config/routes.php that looks like this:
    '(?:[-a-zA-Z0-9@:%_\+.~#?&\/=]+\/)+error/(\d+)' => '_entry',
    This matches any URI that ends with /error/ and a number, and will capture the number as a variable. For an explanation of the regex, here it is on regex101.com.
    Note: The version on regex101.com needs one of the forward slashes escaped, but that slash in config/routes.php should not be escaped.

  2. Create a macro that will look up and return the correct error message by using a switch statement on the error number, which will be captured in the matches variable. The macro looks like this:

{% macro show_error(error_id) %}
  {% switch error_id %}
    {% case 10072 %} Error: bad transaction, please try again
    {% default %} Error: error message not found
  {% endswitch %}
{% endmacro %}
  1. Add code at the beginning of _entry to detect if the matches variable exists, and then:

    • look up what entry would have been loaded by the CraftCMS engine, if this weren't a custom route: {% set entry = craft.entries.uri(matches[0]).first() %}
    • save the error message to a variable, using the previously defined macro: {% set error_message = show_error(matches[1]) %}
  2. Display the error message at the appropriate place in the template:

{% if error_message is defined and error_message|length %}
  <div class="error">{{ error_message }}</div>
{% endif %}`
  1. Result: I can append /error/123 to any entry's URI, and the _entry template will be able to integrate the externally-chosen error message in an internal template.
nmjk
  • 123
  • 5

1 Answers1

2

Probably the easiest way to do this would be to add another segment to your URI. i.e /bla/bla/bla/message-1 Then in your template, read the segment and display the appropriate message. You could do it all in the template with a switch or conditional or the segment could be the entry slug for the message and you can pull from Craft entries.

Jim Wyse
  • 451
  • 2
  • 7
  • I can work with that! It's not quite "arbitrary message" but I could use a macro in the base layout template, and just add any error messages I ever need to the "errors" macro. And it's probably more advisable to do it that way, anyway, rather than allowing arbitrary input, no matter how much I trust my own programming. ;) – nmjk Jun 01 '18 at 18:16