Yii2 SEO friendly URLs with extra parameters in PATH

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_description/item_id

The orgname is included for SEO reasons

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>',</id></controller></id:d+></controller:w+></orgid:d+></orgname:w+>
           '<orgname:w+>/<orgid:d+>/<controller:w+>/<action:w+>/<id:d+>' 
                   => '<controller>/<action>',</action></controller></id:d+></action:w+></controller:w+></orgid:d+></orgname:w+>
           '<controller:w+>/<id:d+>' 
                   => '<controller>/view',</controller></id:d+></controller:w+>
           '<controller:w+>/<action:w+>/<id:d+>' 
                   => '<controller>/<action>',</action></controller></id:d+></action:w+></controller:w+>
           '<controller:w+>/<action:w+>' 
                   => '<controller>/<action>',</action></controller></action:w+></controller:w+>
           '<action:w+>' 
                   => 'site/<action>',</action></action:w+>
       ],
   ],

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 frontendcomponents;
   
  use Yii;
  use yiiwebController;
  use commonmodelsOrganization;
   
  /**
   * 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;
          
      }
  }

2. Extend the URLManager

  namespace appcomponents;
   
  use yiiwebUrlManager;
  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);
      }
  }

3. Call new URL manager

$url=XUrlManager::createXUrl('controller/action');

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

Let’s Start a Project!

Contact Me