routescontrollerrulessymfony-2.8

Symfony v2.8 - Overloaded Router (different sets of parameter) for the same action function/method


I've seen several answers to this question, where some say it can be done, some say it can be done (but it is a bad idea), and some say no.

I've have the following router annotation and action function/method:

/**
 * @Route( "/ctlr/manageAccount/{action}/{username}/{loginDateTime}/{code}/{password}",
 *         requirements={ "action"        = "activate|unlock|passwordReset|changePassword|action",
 *                        "username"      = ".*",
 *                        "loginDateTime" = ".*",
 *                        "code"          = "[\d\w]*",
 *                        "password"      = "[^\s]*" } )
 */

public function manageAccountAction( $action, $username,
                                     $loginDateTime='', $code=FALSE,
                                     $password='' ) { ... }

About 80% of the code in the manageAccoungAction function/method is the same for all of the actions, where the parameters are used as follows:

The last three parameters will not be used for all of the $action values, so these are declared as optional.

How do I create the Routing rules for each operation of $action?

$action (r) $username (r) $loginDateTime (o) $code (o) $code (o)
activate non-empty empty non-empty empty
unlock non-empty empty non-empty empty
passwordReset non-empty empty non-empty not-empty
changePassword non-empty non-empty empty not-empty

(r) = Required; (o) = Optional

How do I define the Route rules for the above conditions?

Note, with the Route rule that is shown in the @Route statement, above, the $username contains the user's name and a trailing slash (/), $loginDateTime is '', $code is false, and $password is '' when the user is not logged-in.

When the user isn't logged-in, then the $username contains the user's name, a slash, and the numeric-string that should be in $loginDateTime, $loginDateTime is still '', $code is false, and $password is ''.

Clearly the slashes aren't being used to delimit and distribute the values in the URL:

/ctlr/manageAccountAction/activate/USERNAME//12345
/ctlr/manageAccountAction/unlock/USERNAME//12345
/ctlr/manageAccountAction/passwordReset/USERNAME//12345/NEWPASSWORD
/ctlr/manageAccountAction/changePassword/USERNAME/76543//NEWPASSWORD

Where USERNAME stands for the user's actual username, 123456\ is the user's account data's alternate key, NEWPASSWORD is the user's new password, and 76543 is the logged-in date-time.

Thank you.


Solution

  • There were two things that needed to be changed. First, change the requirements for the username from:

    *                    "username"      = ".*",
    

    to:

    *                    "username"      = "[a-z0-9]*",
    

    It appears that the parsing for slashes (/) in the URL isn't performed first, but at the same time as the requirements check or after, thus the slash between the username and the next value didn't work as expected, because the slash and the next value weren't separated from the username, but instead, run-together.

    The other thing, was to pull out the loginDateTime and password values from the URL and routing rules. This is because of the values and rules, these values and their function parameters are the only ones that are used when the user is actually logged-in. Meaning, that if they remained in with the other operations, that the URL would have two consecutive slashes, which I don't thing would parse correctly. It is better that the change password operation that uses these values and function parameters be placed in a new function.