Introduction
By default, Joomla use JRoute::_()
to handle frontend routing, we must build a URL with queries to create a SEF route.
For example:
echo JRoute::_('index.php?option=com_flower&view=sakura&layout=item&id=25')
Will be
/{MENU}/sakura/25.html
In Windwalker, we provide a routing tool to help developer build URI by a set of custom rules. You can build a route by resource name:
echo \Windwalker\Router\RadRoute::_('com_flower@sakura', array('id' => 25, 'alias' => 'sakura-alias'));
The result will be:
/{MENU}/sakura/25/sakura-alias.html
How It Works
Same as native Joomla routing, you must assign your component and view to core menu items first, now we create a menu with alias: flower
.
And create an item with alias: example
, ID is 7
:
Open frontend component file routing.yml
.
sakuras:
pattern: sakuras/(id)
view: sakuras
sakura:
pattern: sakura/(id)/(alias)
view: sakura
You can see the sakura
item route rule is /sakura/(id)/(alias)
, se we type flower/sakura/7/example
to browser URL bar.
It is very easy to build route with this item, use _()
:
\Windwalker\Router\RadRoute::_('com_flower@sakura', array('id' => 7, 'alias' => 'example'));
The return value will be:
/{YOUR_SITE_PATH}/flower/sakura/7/example
Or use shortcut by component built-in router, which supports ignoring the component option for route name:
// No longer need `com_flower@`
\Flower\Router\Route::_('sakura', array('id' => 7, 'alias' => 'example'));
But you can still build other components' routes by add option prefix:
// Build com_animal's route
\Flower\Router\Route::_('com_animal@bear', array('id' => 25, 'alias' => 'bear-alias'));
Use Other Route Styles
/(id)-(alias)
Style
You can use (id)-(alias)
style to make your URI. Follow this rules:
# ...
sakura:
pattern: sakura/(id)-(alias)
view: sakura
requirements:
id: \d+
The requirements.id: \d+
use regex to limit id value must be an integer, so all string after id
will be alias
.
You can get variables in controller:
$id = $this->input->get('id');
$alias = $this->input->get('alias');
Mutiple Level Routes
You can also add categories path for sakuras
list page, for example:
sakura_category:
pattern: /category/(*path)
view: sakuras
Route::_('sakura_category', array('path' => $category->path));
Will be:
/{YOUR_SITE_PATH}/flower/category/first/second/third
In controller, you can get path as an array:
$this->input->getVar('path');
/*
Array
(
[0] => first
[1] => second
[2] => third
)
*/
Patterns
Simple Params
Use parenthesis ()
to wrap param name.
pattern: /flower/(id)/(alias)
For uri look like : /flower/25/article-alias-name
, above pattern will be matched and there will be two input params.
[id] => 25
[alias] => article-alias-name
Custom Input Variables
pattern: /flower/(id)/(alias)
variables:
foo: bar
The attributes in variables
will auto set to input if this route be matched.
Limit By Requirement
Use Regular Expression to validate type of input. For example \d+
indicates that only Integer
will be accepted as id
input.
pattern: /flower/(id)/(alias)
requirements:
id: \d+
Optional Params
Single Optional Params
Use (/{anyparam})
to wrap an Optional Param.
pattern: flower(/id)
Below 2 uris will be matched simultaneously.
/flower
/flower/25
Multiple Optional Params
pattern: flower(/year,month,day)
All uris below will be matched.
/flower
/flower/2014
/flower/2014/10
/flower/2014/10/12
Matched variables:
Array
(
[year] => 2014
[month] => 10
[day] => 12
)
Wildcards
Use Wildcards to match all the successive params in uri.
pattern: /king/(*tags)
Every param after /king
will all be matched. For example: /king/john/troilus/and/cressida
, will get these variables.
Array
(
[tags] => Array
(
[0] => john
[1] => troilus
[2] => and
[3] => cressida
)
)
Route Options
Windwalker router provides a set of options to make your rules flexible.
view
sakura:
pattern: sakura/(id)
view: sakura
The view: sakura
means to find FlowerViewSakuraHtml
, it is as same as &view=sakura
in HTTP query.
task
sakura:
pattern: sakura/save(/id)
task: sakura.edit.save
The task: sakura.edit.save
means to find FlowerControllerSakuraEditSave
, it is same as &task=sakura.edit.save
in HTTP query.
You can only contain ont of
task
orview
in route setting.
layout
sakura:
pattern: sakura/(id)
view: sakura
layout: edit
The layout: edit
means to use tmpl/edit.php
in sakura view, it is as same as &layout=edit
in HTTP query.
format
sakura:
pattern: sakura/(id)
view: sakura
format: json
The format: json
means to find FlowerViewSakuraJson
, it is as same as &format=json
in HTTP query.
HTTP Scheme
Only this HTTP setting will be matched.
sakura:
pattern: sakura/(id)
view: sakura
# Only https
scheme: https
post: 80
sslPort: 443
Extra
Extra is some your custom values for this route.
sakura:
pattern: sakura/(id)
view: sakura
extra:
foo:
bar: yoo
Use this way to get extra values from matched route.
\Windwalker\Router\RadRouter::getInstance('com_flower')->extra->get('foo.bar'); //yoo
buildHandler
And parseHandler
sakura:
pattern: sakura/(id)
view: sakura
buildHandler: MyRouteHelper::buildSakura
parseHandler: MyRouteHelper::parseSakura
The *Handler
options means to add hook to build or parse action for this route.
The buildHandler
class MyRouteHelper
{
/**
* Sakura build hook.
*
* @param array $queries The HTTP query get from RadRoute class.
* @param boolean $replace Replace core build rules and only use the return segments from this method.
* @param JMenuSite $menu The Joomla menu object to get menu items.
*
* @return string|array|void Replace, append segments or not, return value can be string or array.
* Only works when $replace = true.
*/
public static function buildSakura(&$queries, &$replace, $menu)
{
// Add custom query data
$queries['my_data'] = 'foo';
// Or return custom segments
$replace = true;
return 'my/custom/segments';
}
}
Now if you build a route by $route::_('sakura', ['id' => 25]);
, the generated URI will be:
/{YOUR_SITE}/flower/sakura/25?my_data=foo
Or return custom segments by setting $replace
to true
.
public static function buildSakura(&$queries, &$replace, $menu)
{
$replace = true;
unset($queries['id']);
unset($queries['alias']);
unset($queries['option']);
return 'my/custom/segments';
}
Result:
/{YOUR_SITE}/flower/my/custom/segments
Use Menu Item Alias
You can replace your route by custom rules, for example, if a menu direct to an item, return menu alias to replace sakura route:
public static function buildSakura(&$queries, &$replace, JMenuSite $menu)
{
// Get all com_flower menus
$menuItems = $menu->getItems('component', 'com_flower');
// Find matched menu item.
foreach ($menuItems as $menuItem)
{
if (isset($menuItem->query['view']) && $menuItem->query['view'] == 'sakura' &&
isset($menuItem->query['id']) && $menuItem->query['id'] == $queries['id'])
{
// Replace core route rule.
$replace = true;
// Only return menu Itemid then Joomla will convert to menu alias
$queries = array('Itemid' => $menuItem->id);
}
}
// No menu matched, follows default rule.
}
The parseHandler
class MyRouteHelper
{
/**
* Sakura parse hook.
*
* @param array $variables The variables parse from URI.
*
* @return array The final variables with your custom data.
*/
public static function parseSakura(array $variables)
{
if (isset($variables['task']) && $variables['task'] == 'sakura.edit.apply')
{
$variables['my_data'] = 'bar';
}
return $variables;
}
}
ParseHandler is much simpler, just add or delete what you need of variables, and return it. Then you can get data by Input.
$this->input->get('my_data'); //bar
Found a typo? Help us improve this document.
This document is for Windwalker Joomla RAD, if you are finding Windwalker PHP framework, please see: Windwalker Framework