Controller instantiation in Yii framework by directory and namespace

1.5k views Asked by At

Yii framework supports modules and also subdirectories in controllers directory, so path to some specific action could be

  • /index.php?r=module/controller/action or
  • /index.php?r=subdirectoryInControllerDir/controller/action.

My goal here is to have multiple subdirectories in the controllers directory. Inside these folders I would create controllers with the same names as parent ones using namespaces.

However if I write

namespace mynamespace;
class MyController extends \MyController {
}

Yii would load MyController instead of mynamespace\MyController;

Any suggestions here?

1

There are 1 answers

0
JonathanStevens On

Yii uses an intuitive naming convention for namespaces, which starts from \application and must follow the physical directory structure, like the built-in autoload config. If your base MyController class is in protected/controllers/, then it should use namespace application\controllers;

<?php
namespace application\controllers;
class MyController extends \CController
{
    // actions
}

and the child MyController in protected/controllers/subdir/

<?php
namespace application\controllers\subdir;
class MyController extends \application\controllers\MyController
{
    // actions
}

To make a request like "subdir/my" work, you need to add the following code to CWebApplication::createController() (or inherit it in a subclass) right after the class file is included:

    if(!class_exists($className,false))
        require($classFile);
+   if(!class_exists($className,false))
+       $className = '\\application\\controllers\\' . str_replace('/', '\\', $controllerID . $className);
    if(class_exists($className,false) && is_subclass_of($className,'CController'))
    {
        $id[0]=strtolower($id[0]);
        return array(
            new $className($controllerID.$id,$owner===$this?null:$owner),
            $this->parseActionParams($route),
        );
    }

If you have set controllerNameSpace of CWebApplication you can also use that value instead of hardcoding \\application\\controllers\\.