Yii2 routing when using CamelCase action names

2020-02-05 17:55发布

问题:

If you have say the following controller structure

<?php
namespace app\controllers;

use Yii;
use yii\web\Controller;
/**
 * Test controller
 */
class TestController extends Controller
{
    public function actionMyaction(){
       ...
       //action logic
    }

    public function actionMyAction(){
       ... 
      //action logic
    }
}

The first route can be accessed using the path example.com/test/myaction

The second route per Yii 1.x logic should be accessible from the path example.com/test/myAction in Yii2.x routing is using hyphenated structure and is accessible only from example.com/test/my-action

Is there anyway to enable routing using camelCase structure in Yii2 preferably without extending with routing classes ?

This is important as it breaks all link ( which are of course all over the internet) backward compatibility and thus Yii1.x app can never be migrated to Yii2.x even if the code is fully rewritten. What was the reason for this change?

回答1:

I was thrown a little about this change too, but eventually I found it makes the URL easier to read. I was unsure about having a case sensitive route in Yii1, in Yii2 I do not have this problem (or impression of a problem) anymore.

I am not sure about the exact reason, but I can tell you that for SEO it is better to have - separating words instead of having 1 big word.

When I rewrote an application in yii2, I put in the url manager all the old routes that i need to maintain.

        'urlManager' => [
            'class' => 'yii\web\UrlManager',
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'rules' => [
.................................................
                'site/registerInterest' => 'site/register-interest',
.................................................

            ],
        ],

So my old links work now just fine. You can also put a 301 redirect in .htaccess if you want from the old routes to the new ones to keep the SEO juice.



回答2:

You can make your own Basecontroller and overwrite createAction with a pattern allow uppercase like

preg_match('/^[a-zA-Z0-9\\-_]

 public function createAction($id)
{
    if ($id === '') {
        $id = $this->defaultAction;
    }

    $actionMap = $this->actions();
    if (isset($actionMap[$id])) {
        return Yii::createObject($actionMap[$id], [$id, $this]);
    } elseif (preg_match('/^[a-zA-Z0-9\\-_]+$/', $id) && strpos($id, '--') === false && trim($id, '-') === $id) {
        $methodName = 'action' . str_replace(' ', '', ucwords(implode(' ', explode('-', $id))));
        if (method_exists($this, $methodName)) {
            $method = new \ReflectionMethod($this, $methodName);
            if ($method->isPublic() && $method->getName() === $methodName) {
                return new InlineAction($id, $this, $methodName);
            }
        }
    }

    return null;
}