How To Deal With Complex URLs In OctoberCMS?

- 1 answer

I'm new to octoberCMS! Consider that I've been developing with other types of CMSes where they usually deal with urls automatically. So let's consider we have a website with Countries with their relative States and Cities. All of these of course use relationships in Models.

If I create this page with the url


I can easily access the content by querying the country slug


If I want to access the city of Philadephia I would have something like this


So this would work


BUT to make this actually work and unique you need to check that the Model "City" has that exact country and state connected to it. Otherwise if you only check the last parameters :city-slug this would create false or worse infinite duplicate content where every combination of state/country could work with Philadelphia so that this URL could work as well


Is this the correct way do it? So that every URL with multiple parameters needs to be checked manually in the backend? Or I missing something here? This method seems extremely complicated for very long URLs and not very practical for actual dynamic content.



It looks complex but its really simple, You just need to check at a time and the just need to redirect to proper location when needed.

Just use this slug/:country-slug?/:state-slug?/:city-slug?

You can see we are making all 3 optional.

In this way you can actually log request and know which items are being searched and which slugs are wrong. ( need to add your custom logic )

  1. If there is no correct country redirect to error page or help explaining you need to provide correct country name
  2. If country is ok then show its content.
  3. If country is ok and state is not then just redirect them to country page to avoid lot of duplicate content and error messages.
  4. If country and state is ok show country, state content.
  5. Same goes for city...

Now in your component or in template you can do something like this.

use Country;
use State;
use City;

function onStart()
    $whatToShow = 'country';
    $country = Country::where('slug', $this->param('country-slug'))->first();
    if(!$country) {
        // if we cant find correct country then no go
        return Redirect::to('/not-found-page');
    $this['country'] = $country;
    $this['state'] = null;
    $this['city'] = null;

    $stateSlug = $this->param('state-slug');
    // check if state slug is there
    if($stateSlug) {
        $state = Country::where('slug', $stateSlug)->first();     
        if(!$state) {
            // if we do not have state then just redirect to country URL
            $countryPageLink = $this->controller->pageUrl(
                null, // <- means same page
                ['country-slug' => $country->slug]
            return Redirect::to($countryPageLink);
        $this['state'] = $state;
        $whatToShow = 'state';

    $citySlug = $this->param('city-slug');
    // check if city slug is there
    if($citySlug) {
        $city = City::where('slug', $citySlug)->first();     
        if(!$city) {
            // if we do not have city then just redirect to country/state URL
            $statePageLink = $this->controller->pageUrl(
                null, // <- means same page
                ['country-slug' => $country->slug, 'state-slug' => $state->slug]
            return Redirect::to($statePageLink);
        $whatToShow = 'city';
        $this['city'] = $city;

    $this['whatToShow'] = $whatToShow;

In markup

{% if whatToShow == 'country' %}
    show country specific data - or better country partial
    {% partial 'country' item=country %}
{% endif %}

{% if whatToShow == 'state' %}
    {% partial 'country' item=country %}
    show country specific data - or better state partial
    {% partial 'state' item=state %}
{% endif %}

{% if whatToShow == 'city' %}
    {% partial 'country' item=country %}
    {% partial 'state' item=country %}
    show country specific data - or better city partial
    {% partial 'city' item=city %}
{% endif %}

This should work for you without any problem

if any doubt please comment.