I'm building a site with loads of complex itineraries. Entries are in a channel for various reasons, but I want to split the data across subpages, with a URL structure like:


I want to route everything through my _views/itinerary/index template, and then just have a bunch of includes (dates-prices, gallery, etc...) in my index, something like:

{% include ( '_views/itinerary/' ~ craft.request.lastSegment ) %}

In my routes.php I've got:

'itinerary\/(?P<slug>[^\/]+)\/([^\/]+)'                 => '_views/itinerary',
'itinerary\/(?P<slug>[^\/]+)'                           => '_views/itinerary',

So everything is routing fine to _views/itinerary/index. Trouble is, I get a 404 for anything other than /itinerary/name-of-itinerary because Craft uses the last segment to resolve the entry, which is exactly what you'd want normally. But if the last segment is 'dates-prices' or 'gallery' I'm screwed.

Have I set this up right? Is there a more efficient and complete way? Any help much appreciated.

1 Answer 1


The route/template for '/itinerary/name-of-itinerary' will be defined in the section's settings, so it's the others you need to deal with.

I'd add this route to your routes.php file:

'itinerary/(?P<entrySlug>[-\w]+)/(?P<subpageSlug>(dates-prices|gallery|etc))' => '_views/itinerary/index',

And then in '_views/itinerary/index' I'd include these conditionals:

{% if entry is not defined %}
    {% set entry = craft.entries.section('itineraries').slug(entrySlug).first() %}
{% endif %}

{% if not entry %}
    {% exit 404 %}
{% endif %}

On your subpages, the entry model object won't be available by default so you need to check whether it's defined, and if not define it.

  • Outstanding Jamie, thanks a lot. Totally makes sense now.
    – Ian Ebden
    Commented Sep 7, 2015 at 21:11
  • This is also worth a read: buildwithcraft.com/docs/routing In your case, #6 would apply here: If you setup your template structure like your URLs, Craft will display the proper template based on the URL. Handy in some instances. Commented Sep 8, 2015 at 22:58

Your Answer

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

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