Got a tip? Let us know


Implementing pretty and SEO friendly URLs in Yii2 application

June 17,2019 8 comments

The importance of an SEO friendly URL can never be stressed enough. A well-structured URL improves the chances of your website ranking highly in search engines. It also helps your users have a rough idea of what is on the page before navigating to it.

In this tutorial, we are going to discuss how routing and URL creation is handled in Yii2 and how to make pretty and SEO friendly URLs in Yii2. The tutorial assumes that you have at least a basic understanding of Yii2; how models, views, and controllers work in Yii2 and PHP in general.

Pretty URL or SEO friendly URL are URLs that are immediately meaningful to a non-expert user. For example, a non-pretty URL like http://localhost:8080/index.php?r=site%2Fabout can be turned into a pretty URL http://localhost:8080/site/about

Yii2 Set Up

The first step is to install Yii2. You can skip this step if you have a Yii2 application already installed.A guide on how to set up Yii2 basic can be found in the official Yii documentation.

Upon successful installation, you should be able to see a view similar to this when you visit the homepage.

Successful installation


When you enter a URL in the browser, Yii2 first passes it into a route to determine how it is then handled. A route consists of a module ID (optional), a controller ID which uniquely identifies the controller and finally an action ID which uniquely identifies an action among all actions within the same controller.

Routes can take the following format:


Or the following format if the controller belongs to a module:


So if you enter the URL http://localhost:8080/index.php?r=site%2Findex in the browser. Then actionIndex a function within the SiteController class in controllers/SiteController.php is executed.

The URL Manager

The URL manager component in Yii2 is responsible for parsing incoming request into routes and associated parameters and also for creating URL from the respective route and associated query. URL manager supports two formats: the parameter based format (default) and the pretty URL based format. By default, you can access the URL manager from the web.php file in the config folder.

Default Route

In Yii2, whenever a URL cannot be passed to a specific route, the default route is used instead. The default route is site/index. This can be customized by setting the defaultRoute in the config array shown below:

$config = [
   'defaultRoute' => '/site/landing', 
    'components' => [
        'urlManager' => [

Catch-All Mode

To turn off all routes and go into maintenance mode, all need you to do is to configure the catchall property in the config array. Update config/web.php as shown below to test.

$config = [
   'catchAll' => ['site/offline'], 

Implementing Pretty URLs

As earlier established, this simply means settings up URLs that appear as though they are folder paths (/foo/bar), when they are actually query string parameters (?foo=bar)

To enable pretty URL, you need to set enablePrettyUrl as true and showScriptName to false in the urlManager component in the config file.

showScriptName determines whether the entry script should be included in the URL. For example, if set to false, then index.php/site/index becomes /site/index

It should be as follows:

$config = [
// more configuration here
    'components' => [
	// more configuration here
        'urlManager' => [
	   // Disable index.php
           'enablePrettyUrl' => true,
	   // Disable r=routes
           'showScriptName' => false,
           'enableStrictParsing' => false,
           'rules' => [
              // ...

Apart from this, you also need to create an htaccess file and enable mod_rewrite for this to work in Apache servers.

RewriteEngine on
# If a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Otherwise forward it to index.php
RewriteRule . index.php

Configuring URL Rules

To parse the incoming request and create URLs, the URL manager uses the rules declared in its rules property.

The rules can either be set as a key => value with the key being the pattern and value being the route.

Edit controller/SiteController and add the following code:

 public function actionView($id){
   echo $id;

Then add this to the config/web.php as shown below:

'rules' => [
 'about' => 'site/about',
 'site/<id:\d+>' => 'site/view',

In the above example, the first rule matches a URL about and maps it to the route site/about. The second rule matches the URL matching the regular expression post/(\d+) and maps it to a route post/view with a parameter named id

The second way to set rules is setting them in a configuration array as shown below:

'rules' => [
  'pattern' => 'contact',
  'route' => 'site/contact',
  'suffix' => '.html',

This method is usually appropriate when you want to override the previous rules and configure other properties of a rule.

URL Suffixes

You can go further and make the URLs even prettier by adding the suffix property like .json or .html. For customized rules, you can add the suffix property as shown above.

'urlManager' => [
 'suffix' => '.html',
 'rules' => [
   'pattern' => 'contact',
   'route' => 'site/contact',
   'suffix' => '.html',

Parameters Routes

To allow a URL rule to be used to match multiple routes, you can embed parameters in the route of a URL rule. For example, the rules below embeds the controller and action parameters in the routes of the rules.

Add the following code to /controller/SiteController:

public function actionUpdate( $id ) {
      echo "update ".$id;

Then update config/web.php as shown below:

 'urlManager' => [
           'rules' => [
              '<controller:\w+>/<id:\d+>' => '/view',
              '<controller:\w+>/<action:\w+>/<id:\d+>' =>    '/',
              '<controller:\w+>/<action:\w+>' => '/',

The second rule says, if you find a request for a controller followed by a word (\w+) followed by a slash then followed by an action followed by word (\w+) followed by a slash with a number then send the request to a matching controller and invoke an action with the matching name actionAction($id) with number

Let’s break it down further by using a real example. To parse a URL /site/update/update, the second rule will apply, which sets the controller parameter to be SiteController and action parameter to update i.e function actionUpdate in SiteController class. The route / is thus resolved as site/update and 100 is passed as the value for the parameter id.

Rules with Server Names

When you want your application to behave differently on different server names, you can add the server names to the pattern’s property of the URL rules as shown below:

 'urlManager' => [
'rules' => [
 '' => 'admin/user/login',
 '' => 'site/login',

Creating URLs

Yii2 provides a helper function yii\helpers\Url::to() that you can use to generate links based on your URL manager rules.

Here are some examples from the Yii documentation:

use yii\helpers\Url;

// currently requested route: /index.php?r=admin%2Fpost%2Findex
echo Url::to(['']);

// a relative route with action ID only: /index.php?r=admin%2Fpost%2Findex
echo Url::to(['index']);

// a relative route: /index.php?r=admin%2Fpost%2Findex
echo Url::to(['post/index']);

// an absolute route: /index.php?r=post%2Findex
echo Url::to(['/post/index']);

// using an alias "@posts", which is defined as "/post/index": /index.php?r=post%2Findex
echo Url::to(['@posts']);

The URL generated above will obviously be different if you choose to use pretty URLs.

Having to create the URLs manually can be cumbersome, prone to errors and can make maintenance a daunting task. It is therefore recommended that you use the helper function instead.


Routing and URL creation are just some of the inbuilt features in Yii that can help you cut the development time. For more information on how to build robust applications, you can visit the official Yii documentation.

The complete code for this tutorial can be found on GitHub

Mike Lidbary

You can find me on twitter @mikelidbary.

More in this category: Upvote/Downvote Weighted Ranking System in Laravel Using Bayesian Formula ยป


Jirka - Jun 07,2020 at 06:08 pm
Im sorry, i found mistake, there was line '<controller:\w+>/<id:\d+>' => '<controller>/view', - which was ruining it.
Sergggr - Jan 15,2021 at 11:48 am
Svetlanadna - Jan 17,2021 at 07:02 am
Ivanqys - Jan 19,2021 at 03:11 am
Svetlhet - Jan 21,2021 at 01:24 am
Igorhzb - Jan 22,2021 at 07:00 am
Evairz - Jan 24,2021 at 09:52 am
Davidsxh - Jan 26,2021 at 03:48 am

Add Comment