Search code examples
phpyii2yii2-urlmanager

How to implement the patterns array in the urlManager of web.php?


I have a Yii2 app. And I try to add the patterns array in the urlManager of web.php. And I serached a lot and fount a lot of links with the correct soltuion. For example:

https://stackoverflow.com/questions/41873686/yii2-apply-custom-url-rule-class
https://www.yiiframework.com/doc/guide/2.0/en/runtime-routing

But It didn't resolved the issue.

So if I do it like:

'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            
            'rules' =>  [
                'class' => 'yii\rest\UrlRule', 
                'controller' => 'v1/user', 
                'POST' => 'v1/user/signup',
                'POST' => 'v1/user/login',
                
                
            ],                          
            
        ],

And in postman I do a post on this url: http://localhost:8080/v1/user/login

everything works fine. But if I do this:

        'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            
            'rules' =>  [
                'class' => 'yii\rest\UrlRule', 
                'controller' => 'v1/user', 
                'patterns' => [
                    'POST' => 'signup',
                    'POST login' => 'login',
                    'OPTIONS login' => 'options',                    
                ],
                
                
            ],                         
            
        ],

the whole web.php file looks:

<?php
// phpcs:ignoreFile

$params = require __DIR__ . '/params.php';
$db = require __DIR__ . '/db.php';

$config = [
    'id' => 'basic',
    'name' => 'internetsuite 2.0',
    'basePath' => dirname(__DIR__),
    'bootstrap' => ['log'],
    'aliases' => [
        '@bower' => '@vendor/bower-asset',
        '@npm'   => '@vendor/npm-asset',
    ],
    'modules' => [
        'v1' => [
            'class' => 'app\modules\v1\Module',
        ],
    ],
    'components' => [
        'request' => [

            'parsers' => [
                'application/json' => 'yii\web\JsonParser',
            ],
            // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
            'cookieValidationKey' => 'OEtCunrAfQNETtmUSDnZw1JPHTB44i3A',
        ],
        

        'cache' => [
            'class' => 'yii\caching\FileCache',
        ],
        'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => true,
        ],
        'errorHandler' => [
            'errorAction' => 'site/error',
        ],
        'mailer' => [
            'class' => \yii\symfonymailer\Mailer::class,
            'viewPath' => '@app/mail',
            // send all mails to a file by default.
            'useFileTransport' => true,
        ],
        'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
                [
                    'class' => 'yii\log\FileTarget',
                    'levels' => ['error', 'warning'],
                ],
            ],
        ],
        'db' => $db,
        'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'enableStrictParsing' => true,
            
            'rules' =>  [[
                'class' => 'yii\rest\UrlRule', 
                'controller' => 'v1/user', 
                'pluralize' => false,
                ],
                'extraPatterns' => [
                    'OPTIONS {login}' => 'options',                    
                    'POST signup' => 'signup',
                    'POST login' => 'login',
                ],
                
                
            ],                         
            
        ],

    ],
    'params' => $params,
];

if (YII_ENV_DEV) {
    // configuration adjustments for 'dev' environment
    $config['bootstrap'][] = 'debug';
    $config['modules']['debug'] = [
        'class' => 'yii\debug\Module',
        // uncomment the following to add your IP if you are not connecting from localhost.
        //'allowedIPs' => ['127.0.0.1', '::1'],
    ];

    $config['bootstrap'][] = 'gii';
    $config['modules']['gii'] = [
        'class' => 'yii\gii\Module',
        // uncomment the following to add your IP if you are not connecting from localhost.
        //'allowedIPs' => ['127.0.0.1', '::1'],
    ];
}

return $config;

I get this error:

Unknown Property – yii\base\UnknownPropertyException
Setting unknown property: yii\web\UrlRule::POST

And I need the OPTIONS parameter because I call an api call from an react app.

Question: how to implement the pattern in the urlManager correctly?


Solution

  • I've found the problem in your whole web.php config code. You put 'extraPatterns' outside the rest rule configuration so it's treated as another rule instead of part of rest rule.

    'urlManager' => [
                'enablePrettyUrl' => true,
                'showScriptName' => false,
                'enableStrictParsing' => true,
                
                'rules' =>  [[
                    'class' => 'yii\rest\UrlRule', 
                    'controller' => 'v1/user', 
                    'pluralize' => false,
                    ], // <-- THIS SHOULDN'T BE HERE
                    'extraPatterns' => [
                        'OPTIONS {login}' => 'options',                    
                        'POST signup' => 'signup',
                        'POST login' => 'login',
                    ],
                    // Here should end the yii\rest\UrlRule configuration
                    
                ],                         
                
            ],
    

    So correct configuration should look like this:

    'urlManager' => [
        'enablePrettyUrl' => true,
        'showScriptName' => false,
        'enableStrictParsing' => true,
        'rules' => [
            [
                'class' => 'yii\rest\UrlRule', 
                'controller' => 'v1/user', 
                'pluralize' => false,
                'extraPatterns' => [
                    'OPTIONS {login}' => 'options',                    
                    'POST signup' => 'signup',
                    'POST login' => 'login',
                ],
            ],    
        ],
    ],
    

    Side note: I don't know why you put login inside of braces like this {login} but it doesn't feel right. OPTIONS login would match OPTIONS request send to route like this v1/user/login. When you put it inside braces you are telling UrlRule to replace it with token defined in $tokens array.