Skip to content

URL Rules

When dealing with modules, several actions and pages you may would like to use nice readable urls instead of the default routing behavior. To do so, you can configure each module with URL rules corresponding to a route.

Configure rules

To configure a new rule you have to open the module file (Module.php) of the luya\base\Module where you want to add new URL rules. Now you can add rules to the luya\base\Module -> $urlRules property, which is an array where you have to add a new item. Each item must contain a route and a pattern.

php
<?php
namespace app\modules\estore;

class Module extends \luya\base\Module
{
    public $urlRules = [
        [
            'pattern' => 'my-basket',
            'route' => 'estore/basket/index',
        ],
        'my-basket' => 'estore/basket/index', // which is equals to the above
    ];
}

The possible URL rule keys if not the short form is used.

KeyDescription
patternThe newly defined name for the rule which is what the end-users see.
routeTo internal route used to determine the new location, based on the Yii 2 routing concept module/controller/action.
defaultsProvide default values for a given pattern param 'defaults' => ['date' => 0]
compositionProvides the option to defined multi-lingual patterns for a given language 'composition' => ['fr' => 'estore/panier', 'de' => 'estore/warenkorb']

You can also use parameters in URL rules:

php
'article-detail/<id:\d+>' => 'estore/article/index',

Visit the Yii Documentation for more details about parameters.

CMS Context:

If you are using the module in a CMS context your patterns must be prefix with the module name, otherwise the CMS can not auto replace the new pattern with the CMS context information. For example redirecting from controller foo action index to controller bar action index inside a module both URL rules must be prefix. For foo ['MODULE/name-for-foo-index' => 'MODULE/foo/index'] for bar ['MODULE/name-for-bar-index' => 'MODULE/bar/index'] so they must have the full qualified route with the name of the module used in the config to register the module. Also the patterns must prefix the module name.

CMS Page Context:

When you place a module block in order to render a module controller and the rendered content produces links (for example a user login, and there is a link to another action where user can reset their password) it's important to disable strict render in CMS settings! Edit Pen -> Expert -> Strict URL Parsing -> Disable

Below, a short list of regex expressions you may use to parameterize the URLs:

RegexDescriptionExample
\dMatches any digit/numbers<id:\d+>
\wAny word character (letter, number, underscore)<hash:\w+>
[abc]Only the letters a, b or c<string:[abc]+>
[a-z0-9]All letter chars a-z (only lowercase) and numbers from 0 to 9<alias:[a-z0-9]+>
[a-z0-9\-]Slugable URL rules known as aliases<alias:[a-z0-9\-]+>

When you have defined URL rules for your module you may want to use them in your view and/or controller files to generate the links that the user can click on it. To make links we use the luya\helpers\Url class. Lets assume we create links for the above created rule patterns:

php
\luya\helpers\Url::toRoute(['/estore/basket/index']);

And a the parameterized route:

php
\luya\helpers\Url::toRoute(['/estore/article/index', 'id' => 123]);

It's also possible to make links for given Page IDs or Module Names inside the CMS therefore take a look at CMS luya\cms\helpers\Url which inherits from luya\helpers\Url

Multilingual language patterns

If you have multi-lingual pages you need patterns for different languages which can be defined in your $urlRules configuration too. This will only work when defining the rules inside a module. Take a look at LUYA's default luya\web\UrlRule object:

php
public $urlRules = [
    [
        'pattern' => 'estore/basket',
        'route' => 'estore/basket/default',
        'composition' => [
            'fr' => 'estore/panier',
            'de' => 'estore/warenkorb'
        ]
    ],
];

In order to define the URL rules from the urlManager config scope, you can just prefix the route with the given composition pattern. The example above would internally generate the following URL rules in the URL manager:

php
'urlManager' => [
    'rules' => [
        'basket' => 'en/estore/basket/default',
        'warenkorb' => 'de/estore/basket/default',
        'panier' => 'fr/estore/basket/default',
    ],
],

This also means that the given URL rules are available when it's required to point to a certain language like Url::toRoute(['fr/estore/basket/default']) will return panier.

When composition is enabled, it will take the correct route for the current language and prefix the pattern if enable in composition config.

To verify which composition language is used you can dump Yii::$app->composition->langShortCode. The luya\web\Composition component is taking care of LUYA multi language websites and is registered by default for all LUYA projects.

Retrieve Current Rule in CMS Context

When you have a CMS Page as Module or using the Module Block inside a page, the resolved URL rule is accessible via luya\cms\Menu -> getCurrentUrlRule(). This allows you to access the params of the URL rule inside layout files. If there is no URL rule resolved, the return value is null. Below is an example of how to access the method via the menu and an example response:

php
var_dump(Yii::$app->menu->getCurrentUrlRule());
/*
(
    [module] => gallery
    [route] => gallery/alben/index
    [params] => Array
        (
            [catId] => 3
            [title] => food
        )

)

The above route is defined in the Gallery Module with the following value:

php
public $urlRules = [
    ['pattern' => 'gallery/kategorie/<catId:\d+>/<title:[a-zA-Z0-9\-]+>/', 'route' => 'gallery/alben/index'],
];

Application Controller Routes

When the CMS module is enabled it will take over all URLs who are not covered by URL rules in the URL manager, otherwise the CMS won't have the ability to generate pages with slugs and nested subpages. When working with "default" Yii Framework controllers an URL rule is required to get accessable web URL. Let's assume we have a controller which returns data for an async request, we would like to access the URL in order to make an AJAX call somewhere in the layout.

Create the controller, change response format to JSON and return an array:

php
class AjaxController extends \luya\web\Controller
{
    public function actionData()
    {
        return $this->asJson(['foo' => 'bar']);
    }
}

In order to get an URL which is accessable, we need to set an URL rule in the config of the components section:

php
'urlManager' => [
    'rules' => [
        'ajax-data' => 'ajax/data',
    ]
]

Now the URL creation can be done with the luya\helpers\Url helper, as the rule will take precedence over the CMS luya\cms\frontend\components\CatchAllUrlRule :

php
$url = \luya\helpers\Url::toRoute(['/ajax/data']);