5

I've yet to come up with a decent solution for this so thought I'd throw this out there.

Basically I have a /news/index template, it serves the initial set of news results, and also serves up paginated results and category results, for example:

  • /news/P10
  • /news/category/blogging

My question is: What is the best way to get EE to throw a proper 404 error on a url like /news/foo

Most sites I've seen don't cater for this, even Ellislab: http://ellislab.com/blog/foo

But I do see the clever folks at FocusLab have it nailed (http://focuslabllc.com/blog/foo) :)

Any suggestions/tips ?

6

Following on from Eriks post, I've created a global variable for detecting whether the page is a pagination page, and it's set in my master config:

$vars['global:is_pagination'] = (preg_match('/P[0-9]+/', $_SERVER['REQUEST_URI'] )) ? TRUE : FALSE;

and then in my news/index

{if segment_2 != '' && segment_2 != 'category' && global:is_pagination == ''}
{redirect="404"}
{/if}

So essentially:

  1. if a segment 2 exists
  2. AND it's not 'category'
  3. AND it's not pagination, throw a 404.

Thanks Erik!

  • I really like this approach. Good work :) – Erik Reagan Dec 6 '12 at 13:08
5

We sometimes use

{if segment_3}{if no_results}{redirect="404"}{/if}{/if}

In instances where {segment_3} is the feeder.

  • 1
    so in my instance it would be segment_2, but I don't see how this could work (doesn't for me). /news/foo would trigger the if no_results tag if there were no results, but that's the problem, EE does it's default thing and just outputs all the entries as if it was just the index being rendered? – Iain Urquhart Dec 6 '12 at 1:56
3

Mel touched on part of our approach. We use the require_entry parameter in most channel:entries loops. That's part of the process. Next, we imploy multiple conditionals to check for URL hackers errors.

General URL Structure

We like pretty and concise URLs so our blog/index EE template looks like this in its entirety:

{!--
/**
 * blog/index is a master template that just embeds 1 of 2 other templates based on segment 2. Pretty basic stuff.
 * We're using a custom built extension which registers a global variable "is_pagination_page" so we can use
 * the URL structure we want. It's very basic and I couldn't find any existing add-ons that did what I wanted
 * Add-ons that came close: MD Detect Page Type & Freebie. No dice though.
 */
--}
{if segment_2 == '' OR segment_2 == 'category' OR is_pagination_page}
    {embed="blog/_list"}
{if:else}
    {embed="blog/_entry"}
{/if}

The is_pagination_page global is exactly what the code comments describe.

Blog single entry sample code (blog/_entry)

{exp:channel:entries
    channel="blog"
    disable="category_fields|trackbacks"
    limit="1"
    require_entry="yes"
}
{if no_results}{redirect='say-what'}{/if}
{if segment_3 != ''}{redirect='{segment_1}/{segment_2}'}{/if}
...

Blog listing page (blog/_list)

To check category url pages we use Low Seg2Cat to make sure it's a legit category. (It it's not a real category, the global variable Seg2Cat creates is an empty string.)

{if segment_2 == 'category' && '{segment_3_category_name}' == ''}
    {redirect='say-what'}
{/if}

I hope this helps. It's exactly what we have setup on focuslabllc.com right now. We have some 404 checks on other sections but these seem to be the ones applicable to the question at hand.

  • Note that we set this up pre-Switchee. You can use that to match our conditional approach and not need the is_pagination_page variable. – Erik Reagan Dec 6 '12 at 2:34
  • Yeah, it's the pagination component that got me stuck, I'll look at creating a global for detecting if pagination is being called. Thanks for your clear answer. Can I ask why you redirect instead of throwing a 404? – Iain Urquhart Dec 6 '12 at 2:44
  • 1
    The redirect was to better handle headers. I could have displayed "no entry" messages but then would have to set the 404 header myself. I preferred to just let EE do it in this case (which it does with a properly defined 404 template). – Erik Reagan Dec 6 '12 at 3:35
  • Sure, but I thought redirect="my404template" didn't send the 404 headers? interesting... So redirect="404" serves your 404 template in and keeps the url the user was requesting, and redirecting to your 404 template redirects AND serves a 404 header... Learn something new every day. – Iain Urquhart Dec 6 '12 at 7:26
2

what about using require_entry="yes"

http://ellislab.com/expressionengine/user-guide/modules/channel/channel_entries.html#require-entry

Then {if no_results}{redirect="404"}{/if}

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.