4

Ok, I am transitioning an app from yii 1.1 to yii 2, unfortunately I cannot figure out how to use optional parameters within my url routes. Even when I set defaults in the urlmanager in config I can't state the second parameter without the first one or I end up with a 404 error.

Is there a way to replicate optional url parameter rules such as

array( '<controller:\w+>/<action:\w+>?(/<status>)?',
'pattern' => '<controller>/<action>'                   
),

in yii 2 ?

tarleb
  • 19,863
  • 4
  • 51
  • 80
mezlad
  • 41
  • 1
  • 3

3 Answers3

7

This is not very clear in the documentation (see http://www.yiiframework.com/doc-2.0/guide-runtime-routing.html), but here is the answer:

By default, all parameters declared in a rule are required. If a requested URL does not contain a particular parameter, or if a URL is being created without a particular parameter, the rule will not apply. To make some of the parameters optional, you can configure the defaults property of a rule. Parameters listed in this property are optional and will take the specified values when they are not provided.

So your route must be expressed like:

array(
  'pattern' => '<controller:\w+>/<action:\w+>/<status>',
  'route' => '<controller>/<action>',
  'defaults' => array('status' => '<a default value for status>')
)
CedX
  • 3,854
  • 2
  • 36
  • 45
  • I realized that the defaults have to be set, so if the value was not set, the default value appears in the URL. In my opinion its not the most convenient way to operate but it works so I will work with it. Thanks again. – mezlad Nov 18 '15 at 12:14
  • Its not that efficient, but using it for now. till some better solution found for this. – Mannya Jan 28 '21 at 07:38
2

If you don't want to use Default and stick to the short syntax, you can define 2 rules instead, make sure the "longer" rule is higher in the list:

rules : [
    <controller:\w+>/<action:\w+>/<status> => '<controller>/<action>',
    <controller:\w+>/<action:\w+> => '<controller>/<action>',
]

First rule will trigger if it matches an URL with status element and send you to the controller/action.
Second rule will trigger if first one is skipped. Make sure that your method has a default value for $status.

d.raev
  • 9,216
  • 8
  • 58
  • 79
0

After alot of search I found this solution.in your rules you must set two parameter:

array(   
   'pattern' => '<controller: \w+>/<action:\w+>/<status>',    
   'route' => '<controller>/<action>',   
),
array(
   'pattern' => '<controller:\w+><action:\w+>',
   'route => '<controller>/<action>',  
)

then go to your controller action and add this:

public function action...(/*Your inputs except status*/)
$get = Yii::$app->request->get();
$status = $get['status'] ?? null;

and then you can check $status value without default value.
note: if your parameter is a post parameter change get() to post().

PouriaDiesel
  • 660
  • 8
  • 11