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 mysite.com/<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.
Extend Controller and put code in here to store org_id if present
<?php
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() {
parent::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'];
}
else
Yii::$app->params['organization_id']=0;
}
}
Extend the URLManager
<?php
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
$route=$params[0];
// add on the bits we want org_name/org_id
$route=Yii::$app->params['organization_name']."/".Yii::$app->params['organization_id']."/".$route;
// put the new route back into array
$params[0]=$route;
// just in case, get rid of org_id from parameters in url eg: controller/action?orgid=x
if (array_key_exists('orgid',$params))
{
unset($params['orgid']);
}
}
// call the regular urlManager
$urlManager = Yii::$app->urlManager;
return $urlManager->createUrl($params);
}
}
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: