2
votes

I have been spending quiet some time figuring out how this works - so thought lets ask the question here.

I do understand how to customize URL's in Joomla with the help of router.php - at least I thought so. It is simple to create something like this

domain.com/country/id

example:

domain.com/germany/12

However, you wouldn't know that the id stands for a city. So in this example lets assume the city with id 12 is Berlin.

So for my custom component (named: countries) I would like that the following is displayed:

for view=countries (1st level)

domain.com/country

i.e.:

domain.com/germany

for view=city (2nd level)

domain.com/country/city-id

i.e.:

domain.com/country/berlin-12

(or perhaps just: domain.com/country/berlin - but I think the ID is required for the custom component to work - and any related modules on the page that read the ID to know what to do)

What do I have so far:

function CountriesBuildRoute(&$query)
{
    $segments = array();
    //if(isset($query['view'])) {
    //    $segments[] = $query['view'];
    //    unset( $query['view'] );
    //}
    if (isset($query['task'])) {
        $segments[] = implode('/',explode('.',$query['task']));
        unset($query['task']);
    }
    if (isset($query['id'])) {
        $segments[] = $query['id'];
        unset($query['id']);
    }
        if (isset($query['name'])) {
        $segments[] = $query['name'];
        unset($query['name']);
    }

    unset( $query['view'] );    

    return $segments;
}


function CountriesParseRoute( $segments )
{
       $vars = array();
       $app =& JFactory::getApplication();
       $menu =& $app->getMenu();
       $item =& $menu->getActive();
       // Count segments
       $count = count( $segments );
       //Handle View and Identifier
       switch( $item->query['view'] )
       {
               case 'countries':
                       if($count == 1) {
                               $vars['view'] = 'city';
                       }

                       break;
               case 'city':
                       $id   = explode( ':', $segments[$count-2] );
                       $name   = explode( ':', $segments[$count-1] );
                       $vars['id']   = $id[0].'-'.$name;
                       break;
       }
       return $vars;
}

The way I am calling city pages from view countries is the following:

<a href="<?php echo JRoute::_('index.php?option=com_countries&view=city&id=' . (int)$item->id) .'&name='. $item->city_name; ?>">

Would be amazing if someone can help ! Cheers

1
Two questions: is that all the urls that you will have for the component? And do you have an menu items pointing to either of the views?David Fritsch
Hi David - sorry for late response, was working on a different project and you know how it is... Now this is not the only URL i have and there are no menus pointing to it. It's within the component.Georg Keferböck

1 Answers

0
votes

If you want to get ride of IDs from urls you will have to add every country menu item or create rooter that will search for item id within database (bad idea with big websites). This will also require setting your homepage to one of your component views. Its easiest way.

When you build router you need two functions. First that will return SEF url CountriesBuildRoute and second that will translate SEF url back to query CountriesParseRoute. It is harder then you actually think to write SEF at this level. I will not write you whole router but only point you to right direction.

In Joomla 1.5 it was easier to make smth you want. If you have time look in rooter from some Joomla 1.5 component like (com_weblinks). CountriesBuildRoute returns array that will build your URL. For example when you return $query array looking like this: array('country','berlin') url will look like you want: domain.com/country/berlin. But reversing that process (something you will do in CountriesParseRoute) gonna be harder. You will have to check if first segment is a country (if it is second should be city).

So in function CountriesBuildRoute check what view is passed and build $segments array directly like you want for your url or selected view to be. Remember that single element from that array will be single segment from URL.

In function CountriesParseRoute check if first array element is a country (db checking, cached countries list, there are many ways to do it) then you will have to do the same with second element from array(if it exists).

I always created BuildRoute first as I wanted. Then spend hours on making parse route as precise and effective as only could be. You can spend hours or even few days if you want to make good router.