Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Yii2 route using yii\rest\UrlRule with several parameters

I am trying to use Yii 2 routing for REST API.

Following tutorial at http://www.yiiframework.com/doc-2.0/guide-rest-routing.html, I have already defined (with success) a lot of rule for API entry point like so :

'urlManager' => [
    'enablePrettyUrl' => true,
    'enableStrictParsing' => true,
    'showScriptName' => false,
    'rules' => [
        [
            'class' => 'yii\rest\UrlRule', 
            'controller' => 'user'
        ],
    ],
]

Such a rule defines :

  • GET /users (list users)
  • GET /users/123 (show detail of user 123)

Now, my users have games. So I'd like to have urls :

  • GET /users/123/games (list games of user 123)
  • GET /users/123/games/864 (details of game 864 for user 123 - such as his scores)

I tried defining my new entry point (withhout success) like so:

'rules' => [
    ... previous rules ...,
    [
        'class' => 'yii\rest\UrlRule',
        'controller' => [
            'game'
        ],
        'tokens' => [
            '{userid}' => '<userid:\\d>',
            '{gameid}' => '<gameid:\\d>',
        ],
        'patterns' => [
            'GET,HEAD /users/{userid}/games' => 'index',
            'GET,HEAD /users/{userid}/games/{gameid}' => 'view',
        ]
    ]
]

This definition seems wrong because I get a 404 Page not found error. How should I define my new url routes ? I would like to use an equivalent format for my definitions, extending 'yii\rest\UrlRule'

I am not sure if this is even possible, the tutorial not mentionning this case.

like image 510
Mat Avatar asked Mar 16 '23 23:03

Mat


2 Answers

So I figured out how to use more complex rules.

First, the solution, then the explanation.

Here is the solution:

'rules' => [
    ... previous rules ...,
    [
        'class' => 'yii\rest\UrlRule',
        'controller' => 'game',
        'prefix' => '/users/<userid:\\d+>',
        'tokens' => [
            '{gameid}' => '<gameid:\\d+>',
        ],
        'patterns' => [
            'GET,HEAD' => 'index',
            'GET,HEAD {gameid}' => 'view',
        ]
    ]
]

And now the explanation:

  • First my userid / gameid attributes were badly defined. There was a missing "+" after "\d"
  • The controller seems to be automatically added as a prefix to the patterns. So you have to define both a controller and a prefix (that will be added before the controller).
  • Parameters in the prefix does not seem to be parsed to find tokens. So I wrote directly the regexp in the prefix instead of adding "userid" as a token.
  • Finally, there are various "/" automatically added during concatenation of "prefix/controller/pattern" so you don't have to write one.
  • Do not forget the pluralization rule too ! "game" is singular" but valid urls will be

    • /users/123/games
    • /users/123/games/789

Hope it will help.

like image 94
Mat Avatar answered Mar 24 '23 12:03

Mat


I think there´s a simple solutions, please try this:

'rules' => [
                ...
                '/users/<userId:\\d+>/games' => 'game/index' ,
                '/users/<userId:\\d+>/games/<gameId:\\d+>' => 'game/view' ,
                ....
];
like image 20
VZani Avatar answered Mar 24 '23 11:03

VZani