Yii Url Rules - Optional Parameters

Assume we have an action "articles/get" which accepts optional parameters and we want to setup following URLs:

  • articles/[article id or name]

  • articles/[article id or name]/draft

  • articles/[article id or name]/revisions/99

  • articles/[article id or name]/revisions/98/draft

  • articles/revisions/[revision id]

  • articles/revisions/[revision id]/draft

We have a list of articles and each article has several revisions. Also each revision can have draft and published version.

In the code we have a single ‘article/get’ action which allows us to get specific article (last revision) by name (‘GET articles/my-article’) or id (‘GET articles/33’).

Using additional parameters we can get last revision draft (‘GET articles/33/draft’), get specific revision (‘GET articles/33/revisions/99’) or get article using revision ID only (‘GET articles/revisions/99’).

Now we can setup URL rules for these routes like this:




//- articles/revisions/98/draft

array('article/get', 

  'pattern' => 'articles/revisions/<revision:\d+>/<version:published|draft>', 

  'verb' => 'GET'

),

//- articles/revisions/99

array('article/get', 

  'pattern' => 'articles/revisions/<revision:\d+>', 

  'verb' => 'GET'

),

//- articles/77/revisions/99/draft

array('article/get', 

  'pattern' => 'articles/<article:[\w\d\.]+>/revisions/<revision:\d+>/<version:published|draft>', 

  'verb' => 'GET'

),

//- articles/77/revisions/99

array('article/get', 

  'pattern' => 'articles/<article:[\w\d\.]+>/revisions/<revision:\d+>', 

  'verb' => 'GET'

),

//- articles/77/draft

array('article/get', 

  'pattern' => 'articles/<revision:[\w\d\.]+>/<version:published|draft>', 

  'verb' => 'GET'

),

// articles/77 (or articles/[name])

array('articles/get', 

  'pattern' => 'article/<article:[\w\d\.]+>', 

  'verb' => 'GET'

),



But there is much better option. We can describe this a single URL route with optional parameters (regexp groups with trailing question mark do the trick):




array('app/get', 

  'pattern' => 'apps(/<app:[\w\d\.]+>)?(/updates/<update:\d+>)?(/<revision:published|draft>)?', 

  'verb' => 'GET'

),



The special case is when we need to allow any number of additional parameters at the end of the URL. This case is supported by URL manager:

Can you rewrite example in 1st rule set context?

What do you mean? In my example there is only one rules set which can be described as many rules or as a sinlge rule with optional parameters.

Can you help me with this…


                /*

                 * GET api/orders/<:token>/from/<:from>/count/<:count>

                 * Get Infomration about Orders

                 * Parameters accepted:

                 *      token <required> : User Token

                 *      from <optional> : Start from which order

                 *      count <optional> : How many orders

                 */

                array(

                    'api/order/list/token/<token>',

                    'pattern' => 'api/orders/<token:\w+>',

                    'verb' => 'GET'

                ),

                array(

                    'api/order/list/token/<token>/from/<offset>',

                    'pattern' => 'api/orders/<token:\w+>/from/<offset:\w+>',

                    'verb' => 'GET'

                ),

                array(

                    'api/order/list/token/<token>/count/<limit>',

                    'pattern' => 'api/orders/<token:\w+>/count/<limit:\w+>',

                    'verb' => 'GET'

                ),

                array(

                    'api/order/list/token/<token>/from/<offset>/count/<limit>',

                    'pattern' => 'api/orders/<token:\w+>/from/<offset:\w+>/count/<limit:\w+>',

                    'verb' => 'GET'

                ),

I want to make this short and single rule.

very useful, thanks!

As I understand the "token" parameter is required and "from" and "count" are optional.

It should be something like this:




    array(

        'api/order/list',

        'pattern' => 'api/orders/<token:\w+>(/from/<offset:\w+>)?(/count/<limit:\w+>)?',

        'verb' => 'GET'

    ),