Creating Path Urls


I’ve got url rules as follows which seem to work for inbound requests

'urlManager' => [

        	'enablePrettyUrl' => true,

        	'showScriptName' => false,

	        //'urlFormat' => 'path',

        		'rules' => [

        				'<orgname:\w+>/<orgid:\d+>/<controller:\w+>/<id:\d+>' => '<controller>/view/<id>',

        				'<orgname:\w+>/<orgid:\d+>/<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',

        				'<controller:\w+>/<id:\d+>' => '<controller>/view',

        				'<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',

        				'<controller:\w+>/<action:\w+>' => '<controller>/<action>',

        				'<action:\w+>' => 'site/<action>',



When I try and create a URL using an orgname and orgid, I would have expected these to be part of the url path and not parameters

echo Yii::$app->urlManager->createUrl(["test/action",'orgname'=>'organization','orgid'=>1]);

I would expect this to produce

but instead it producs

As you can see from my config, I’ve tried using ‘UrlFormat’=>‘path’ which, I believe, worked in Yii1.x But I can’t find the equivalent in Yii2

I’ve answered this for myself but it’s not a very elegant solution as it doesn’t strictly run off the url rules. However, it works for me, for now!

The requirement;

  • having clicked to view an organization, I only want to display items for that organization only, so any links must include the organization_id.

I would like to have URLs like<org_name>/<org_id>/item/<item_id>

The orgname is included for SEO reasons

I decided to store the Org_id and org_name in $app->params rather than SESSION. That’s just my choice.

  1. Extend Controller and put code in here to store org_id if present


namespace frontend\components;

use Yii;

use yii\web\Controller;

use common\models\Organization;


 * ActivityController implements the CRUD actions for Activity model.


class ZController extends Controller



    public function init() {



        if (Yii::$app->requestedRoute=='organization/view' || Yii::$app->getRequest()->getQueryParam('orgid')) {

            $id = (Yii::$app->requestedRoute=='organization/view') ? Yii::$app->getRequest()->getQueryParam('id') : Yii::$app->getRequest()->getQueryParam('orgid');

            $org = Organization::find($id)->asArray()->one();

            // make the name URL friendly

            $org = str_replace([' ','\'','"','-'],"_",$org);

            // store the data in params

            Yii::$app->params['organization_id'] = $id;

            Yii::$app->params['organization_name'] = $org['name'];







  1. Extend the URLManager


namespace app\components;

use yii\web\UrlManager;

use Yii;

class XUrlManager extends UrlManager


    public function createXUrl($params = [])


        $params =(array) $params;

        // make sure we have all the data

        if (isset(Yii::$app->params['organization_id']) && isset(Yii::$app->params['organization_name']))


            // grab the requested route


            // add on the bits we want org_name/org_id


            // put the new route back into array


            // just in case, get rid of org_id from parameters in url eg: controller/action?orgid=x

            if (array_key_exists('orgid',$params))





        // call the regular urlManager

        $urlManager = Yii::$app->urlManager;

        return $urlManager->createUrl($params);



  1. Call new URL manager


If you’ve got a better way then please let me know …

btw: I left the URL rules as in my original post …

I’m not an expert but I think your rules are not correct for what you have created.

echo Yii::$app->urlManager->createUrl(["test/action",'orgname'=>'organization','orgid'=>1]);

This will look for a rule whose right-hand-side matches test/action. In your case, that would potentially match the following rules:

'<orgname:\w+>/<orgid:\d+>/<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',

'<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',

'<controller:\w+>/<action:\w+>' => '<controller>/<action>',

It won’t match the first or second because you have not provided the id parameter used on the left-hand-side of those rules. It will instead match the third rule producing what you have seen. To get what you want, the rule would have to be:

'<orgname:\w+>/<orgid:\d+>/<controller:\w+>/<action:\w+>' => '<controller>/<action>'

or possibly replace the id regex + symbol with a * to mean zero or more instead of 1 or more:

'<orgname:\w+>/<orgid:\d+>/<controller:\w+>/<action:\w+>/<id:\d*>' => '<controller>/<action>'