Yii2 SEO friendly URLs with extra parameters in PATH

The requirement;

I've been working on a website which is divided by Organization.  Having clicked to view an organization, the site should only display items for that organization.  And therefore any onward links must also pass on that organization's id onto the following pages.

I would like to have pretty and SEO friendly URLs like mysite.com/org_name/org_id/item_description/item_id

The Organization name is not needed by the website but I have included it 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>',
           '<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>',
       ],
   ],

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() {
          
          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 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);
      }
  }

3. Call new URL manager

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

If you've got a better way then please let me know ...

Did you know you can hire me?

I take on projects of all sizes. From Consulting to large Development Projects.

If you're starting a new Yii project and would like some help to get setup and running or you need some help with a particular module or you just need someone to develop the whole dang thing, then just ask ...


Leave a Comment

twitterfacebookgooglelinkedin https://me.yahoo.com