В этой статье мы рассмотрим особенности роутинга в Joomla при создании ЧПУ ссылкок в модулях или компонентах, а так же создание ссылок на другие компоненты и также принцип построения ЧПУ ссылок.

Итак начнем с построения ЧПУ ссылок! Для этого служит файл router.php, который должен лежать в папке с нашим компонентом пользовательской части!

После того как мы в нашем компоненте или например модуле строку:
JRoute::_('index.php?option=com_mycomponent&view=testview&id=10');
произойдет обращение к функции myComponentBuildRoute в файле router.php
Содержимое этой функции такое:

function myComponentBuildRoute( &$query ){
	$segments = array();
	if ( isset( $query['view'] ) ) {
		$segments[] = $query['view'];
		unset( $query['view'] );
	}
	return $segments;
}

В эту функцию в виде ассоциированного масива в переменной $query придут элементы адресной строки .
тоесть для нашей строки JRoute::_('index.php?option=com_mycomponent&view=testview&id=10'); в переменной $query будет такое содержимое:

Array
(
	[Itemid] => 110
	[option] => com_mycomponent
	[view] => testview
	[id] => 10
)

В функции мы определяем какие участки строки нам не нужны и удаляем их, но если необходимо использовать их значение в дальнейшем, то мы помещаем значение текущей переменной в массив $segments.
Притом в каком порядке мы удалим в таком порядке и будет сформирование ссылка. То есть если мы напишем так:

if ( isset( $query['view'] ) ) {
	$segments[] = $query['view'];
	unset( $query['view'] );
}
if ( isset( $query['id'] ) ) {
	$segments[] = $query['id'];
	unset( $query['id'] );
}

То получим ссылку mycomponent/testview/10

Если напишим:

if ( isset( $query['id'] ) ) {
	$segments[] = $query['id'];
	unset( $query['id'] );
}
if ( isset( $query['view'] ) ) {
	$segments[] = $query['view'];
	unset( $query['view'] );
}

То вид ссылки будет: mycomponent/10/testview

После того как мы переходим по такой же ссылке в браузере то Joomla перехватывает нашу ссылку и определяет какой компонент и вызываает функцию mycomponentParseRoute в файле router.php этого компонента.

Содержимое этой функции приблизительно такое:

function mycomponentParseRoute( $segments )
{
	$vars = array();
	$count = count( $segments );
	if ( $count ) {
		$count--;
		$segment = array_shift( $segments );
		$vars['view'] = $segment;
	}
	if ( $count ) {
		$count--;
		$segment = array_shift( $segments );
		$vars['id'] = $segment;
	}
	return $vars;
}

В переменной $segments приходит обычный массив с содержимым url строки в браузере:

Array (
	[0] => testview
	[1] => 10
)

Порядок значений в массиве будет зависеть от того, в каком порядке у вас удаляются переменный в функции myComponentBuildRoute
. Мы поочередно перебираем каждый элемент массива и создаем ассоциированный массив где ключом будет наша переменная которую мы удалили перед этим, и значение - значение из массива $segments.
Это нужно для того что бы наш компонент знал какие переменные пришли из url запроса, ибо системе не известно где какие переменные в строке mycomponent/10/testview или в строке mycomponent/testview/10

Итак небольшие особенности создания ЧПУ ссылок:
Во первых если вы хотите создать ссылку на вид в текущем компоненте достаточно написать
JRoute::_('index.php?view=имя_вида&переменная=значение&переменная=значение');

Если вы хотите сделать ссылку из модуля на компонент или из другого компонента на текущий компонент ссылка должна формироваться так:
JRoute::_('index.php?option=com_mycomponent&view=имя_вида&переменная=значение'). Притом что если в первом варианте ссылка сформируется с учетом псевдонима пункта меню, то во втором случае при создании ссылки на другой компонент ссылка не учтет псевдоним пункта меню и примет такой вид: mysite.ru/component/mycomponent/testview/10

Если же мы хотим что бы ссылка была с учетом псевдонима пункта меню, созданного в менеджере меню, тоесть например mysite.ru/menualias/test/10 то мы должны добавить к нашей ссылке переменную Itemid значение которой равно полю "ID" нашего меню в менеджере меню, притом что переменную option мы можем упустить:
JRoute::_('index.php?view=имя_вида&переменная=значение&Itemid=110');

Если вы не хотите вручную выставлять значение, а получать Itemid программно, можно воспользоваться следующей функцией:

function getItemid( $component, $view )
{
	$items = JFactory::getApplication()->getMenu( 'site' )->getItems( 'component', $component );
	foreach ( $items as $item ) {
		if($item->query['view'] === $view){
			return $item->id;
		}
	}
}

$itemid = getItemid( 'com_blog', 'category' );