用于管理员的Cakephp自定义文件夹结构

Since my app is getting bigger i would like to separate admin prefix actions and views from normal actions and views. The new folder for admin is Controller/admin/UsersController.php.

I would like to change my cakephp controllers and views folder structure to match the prefix I'm using.

Example for admin prefix:

Controller:

app/Controller/UsersController.php (contain view(), index() ...)  
app/Controller/admin/UsersController.php  (contain admin_view(), admin_index() ...)  

View:

app/View/Users/index.ctp (for index() in UsersController.php)  
app/View/Users/admin/index.ctp  (for admin_index() in admin/UsersController.php)  

How can I implement this structure using Cakephp 2.6?

Unlike in 3.x where this is the default behavior for prefixes, this isn't supported in 2.x.

You could try hacking it in using a custom/extended dispatcher (in order to retrieve the desired controller) or even dispatcher filters in case you are adventurous, and in your app controller modify the view template path with respect to the prefix.

That should do it, however I would probably simply go for using plugins instead, this will separate things just fine without any additional fiddling.

If you just want to separate logic you could do something like this. It's untested an just thought to give you just the idea. I'll explain the concept after the code:

public function beforeFilter() {
    if ($this->request->prefix === 'foo') {
        $name = Inflector::classify($this->request->prefix);
        $className = $name . 'ChildController';
        App::uses($className, 'Controller/Foo');
        $this->ChildController = new $className($this);
    }
}
public function __call($method, $args) {
    if ($this->request->prefix === 'foo' && method_exists($this->ChildController, $method)) {
        call_user_func_array([$this->ChildController, $method], $args);
    }
}

Depending on the prefix you can load other classes. How you load that class and how you instantiate it, what params you pass to it is up to you. In my example I'm passing the controller instance directly. I think you could actually init a complete controller here but be aware that components like the Session might cause a problem because they might have been already initiated by the "parent" controller.

When you now call a controller method that doesn't exist it will try to call the same method with the same arguments on the ChildController. Not really a great name for it, but maybe you can come up with something better.

You'll have to implement some logic to load the views from the right place in your classes as well but this shouldn't be hard, just check the controller class.

But actually I don't see your problem, I've worked on an app that hat over 560 tables and not putting the code into sub folders wasn't a problem, it did in fact use a similar solution.

I think you have to much code in your controllers, get more code into your models and the controller shouldn't be a problem.

Another solution might be to think about implementing a service layer in CakePHP which implements the actual business logic while a model is reduced to a data handler. The service would sit between a controller and the model. I've done this a few times as well now and if done right it works very well.