6

I have a controller that returns route variables to the page:

craft()->urlManager->setRouteVariables(array(
  'errors' => $entry->getErrors()
));

On the page that gets loaded, I can access the variables I set in the template:

{% for error in errors %} ...

However, I want to handle this variable dynamically. Is it possible to access the 'errors' variable in my MyPluginVariable.php file without passing it directly to my variable function?

I don't want to do this:

{{ craft.myPlugin.doSomething(errors) }}

That passes my variable to the plugin variable and I can access it just fine. But I don't want to ask the user to pass this variable to the function every time, I'd prefer to just handle it in the background.

So, on the page that gets loaded, instead of outputting the variable, can I have a Twig tag like this:

{{ craft.myPlugin.doSomething() }}

And directly access the 'errors' variable in my plugin? Something like (this doesn't work):

craft()->request->getRouteVariables('errors')
2
  • 1
    Why don't you do any of your dynamic error processing in your plugin's controller before you return it to the template?
    – Brad Bell
    Jul 12, 2014 at 17:19
  • Maybe I'm missing something. My tag outputs a Form: craft.myPlugin.outputForm() with a single line, so the data I'm getting back is a bunch of stuff that that tag needs to output. When the form is created, the tag just needs to point at the form handle to get all the info it needs craft.myPlugin.outputForm('handle') but if things don't validate, the page reloads and I have an object of submitted values that need to maintain state and errors and I was just wondering if I could avoid doing something like craft.myPlugin.outputForm('handle', values, errors) Jul 12, 2014 at 17:31

2 Answers 2

5
+50

You can’t access the current Twig variables (the “context”, as Twig calls them), from a Template Variable class, but you can access them with a template hook.

From your plugin’s init() function:

craft()->templates->hook('errorCheck', function(&$context)
{
    if (isset($context['errors']))
    {
        // do something with $context['errors'];
    }
});

From your template:

{% hook "errorCheck" %}

You can modify, delete, and create variables within that $context array if you want. And because it is passed by reference (that’s what the “&” does in “&$context”, you won’t need to actually return the array at the end of the function or anything; just make your changes to it.

3
  • Thanks Brandon. It took me a bit to contemplate this and my options to allow the user to only have one tag in the template. I've posted the solution I found to work best below. This is a handy method, and I appreciate the clarification on passing a variable by reference. Oct 5, 2014 at 16:00
  • Should I be able to use this method to retrieve twig variables that are set by a user in the template? e.g. {% set myThing = "foo" %} with $context["myThing"]
    – cmal
    Nov 19, 2015 at 0:39
  • @cmal Yes - anything that is defined at the time the {% hook %} tag is called will be available to your plugin. Nov 22, 2015 at 21:18
2

I ended up solving this by creating a public variable in my service layer and assigning and retrieving the submitted object from there. This helps me keep any new error handling specific code out of the templates for the users, and the output tag can now handle both submitting and error handling in the form.

This method has three parts:

  1. Public variable in the service layer that handles the submitted Form object (this gets set after the submission is validated and gets retrieved, if it exists, when the tag is processed.
  2. Controller that handles the Form submission
  3. Variable in the template file
    craft.sproutForms.outputForm()

More specifically, our service layer has a public variable:

public $activeEntry;

If our submission fails, we assign the submitted object with errors to the $activeEntry variable:

if (craft()->myPlugin->saveEntry($entry)) 
{
   ...
}
else
{
   craft()->myPlugin->activeEntry = $entry;

   ...
}

And, when the page loads and the outputForm() tag is processed, we check to see if that $activeEntry variable is set.

if (isset(craft()->myPlugin->activeEntry))
{
    $entry = craft()->myPlugin->activeEntry;    
}
else
{
    $entry = new MyPlugin_EntryModel();
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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