3

I'm having an odd issue with Stash and a 404 redirect. When an entry isn't found the "layout" template is getting rendered twice around the main Stash content. Anyone seen this before? I can kinda see why it is happening, but can see any way around it. Thoughts?

The page template

{!-- Layout --}
{embed="shared/_layout"}

{!-- Set main content --}
{exp:stash:set 
    name="main_content" 
    parse_tags="yes" 
    parse_depth="2" 
    no_results_prefix="nested"}

  {exp:channel:entries limit="1" url_title="{segment_3}"}
    {if nested:no_results}{redirect="404"}{/if} 
  {/exp:channel:entries}

{/exp:stash:set}

The 404 template

{!-- Layout --}
{embed="shared/_layout"}

{!-- Set main content --}
{exp:stash:set name="main_content"}
  <h1>Page not found</h1>
{/exp:stash:set}

The layout template

<body>
  HEADER GOES HERE!!!
  {exp:stash:get name='main_content'}
  FOOTER GOES HERE!!!
</body>

The resulting output to browser

<body>
  HEADER GOES HERE!!!
<body>
  HEADER GOES HERE!!!

  <h1>Page not found</h1>

  FOOTER GOES HERE!!!
</body>
  FOOTER GOES HERE!!!
</body>

EDIT: Seems I can get around the issue by removing the Stash/layout stuff from the 404 template and just having it as...

<h1>Page not found</h1>

But then a 404 generated by some means other than no_results won't get the layout. Hmm. Ideas?

5 Answers 5

2

If you look at function no_results() in ./system/expressionengine/libraries/Template.php you will see that when a 404 template is defined as simply "404" within a redirect tag, then the 404 template referenced by the config value site_404 is fetched and parsed. The template is not returned by the function but my guess is that it populates the property $EE->template->tagdata with the 404 template tagdata, which Stash will subsequently capture. Hence the apparent recursion.

The solution to this rather odd problem is to simply reference the 404 template by template_group/template, e.g. "site/404" in which case the no_results functions will send a redirect header via $EE->functions->redirect.

6
  • I'm having the same problem but in my case it's happening not only with redirects in templates (which adding site/404 fixes), it's also occurring when EE applies the default 404 template for a non-existent first segment.
    – Tyssen
    Nov 20, 2014 at 0:48
  • Also, do you know if redirecting to a 404 template rather than displaying the broken URL with a 404 header still reports the URL as being 404 to the search engines?
    – Tyssen
    Nov 20, 2014 at 0:50
  • I've just spent a few hours looking again at 404 handling in EE, and now have a new tag {exp:stash:not_found} that will allow you to reliably display the 404 template in all situations, set the 404 header (without needing another add-on/php) and maintain the URL being viewed. Will push to the repo tomorrow. Nov 20, 2014 at 20:18
  • A bit confused as to why the parameter is called unprefix when it appears to be a prefix.
    – Tyssen
    Nov 26, 2014 at 20:42
1

OK. I think I have a solution. Anyone know a better way?

The Page Template

{!-- Layout --}
{embed="shared/_layout"}

{!-- Set main content --}
{exp:stash:set 
    name="main_content" 
    parse_tags="yes" 
    parse_depth="2" 
    no_results_prefix="nested"}

  {exp:channel:entries limit="1" url_title="{segment_3}"}
    {if nested:no_results}
      {exp:stash:set_value name="no_results" value="true"}
    {/if}  
  {/exp:channel:entries}

{/exp:stash:set}

Inside of the layout template

{if {exp:stash:not_empty name="no_results"}}
  {exp:stash:unset name="no_results"}
  {redirect="404"}
{/if}
1

You should turn on your template debug and look for:

Stash: SET or Stash: RETRIEVED

Figuring out if Stash is being called twice is probably where I'd start. If it's a duplicitous call to Stash vs. some Stash internal thing that would be good to know. I have a feeling it's an internal thing that doesn't play nice with the 'redirect' global. I'd have to start commenting out code in Stash to try and nail it down.

1

Just looked a little more. I'm betting it's a parse order thing (http://ellislab.com/expressionengine/user-guide/templates/template_engine.html). Likely the simple conditional is parsing the redirect before Stash is parsed causing some sort of double loop. You're solution is certainly a functional work around.

You might want to try using parse="inward" in the Stash tag, that would probably change the order Stash and the nested elements are parsing and might fix the issue.

0

This could be a documented EE bug which causes the home page template to be rendered after the 404 content. It can be fixed with a small change to a core file.

https://support.ellislab.com/bugs/detail/20471/site-index-template-is-rendered-after-the-404-template

I do note that it says this is fixed in the released version but it was present up to 2.9.0

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.