Phalcon Router and Loader for subfolder structure

2019-05-02 00:29发布

I have a quite big project that I need to program. I used to code with CodeIgniter but since they stopped maintaining the framework, I decided to switch to another. I chose Phalcon framework. The folder structure of the application that I want to implement is next:

  • app/
    • controllers/
      • admin/
        • users/
          • UsersController.php
          • UserGroupsController.php
        • dashboard/
        • system/
        • another_subfolder/
          • AnotherSubFolderController.php
      • production/
        • settings/ SettingsController.php
        • dashboard/
        • flow/
        • another_subfolder/
          • AnotherSubFolderController.php
      • website1/
        • customers/
          • CustomersController.php
          • CompaniesController.php
        • another_subfolder .... /
    • models/
      • sub_folder_structure/ // The same as controllers

This is just example of the folder structure of the application. There will be quite a lot of folders and sub-folders in this project to make it manageable.

From my understanding I need to register all namespaces at the loader for each sub-folder, so that Phalcon knows where to search and load the class.

//Register an autoloader
$loader = new \Phalcon\Loader();

$loader->registerNamespaces(array(
// Main
'Controllers' =>'app/controllers/',
'Models' =>'app/models/',
// Admin Routing
'Controllers\Admin'=>'app/controllers/admin',
'Models\Admin'=>'app/models/admin',
'Controllers\Admin'=>'app/controllers/admin',
'Models\Admin'=>'app/models/admin',
'Controllers\Admin\Users'=>'app/controllers/admin/users',
'Models\Admin\Users'=>'app/models/admin/users'

))->register();

The loader will look quite big.

Then I have to set-up the router so that requests redirected to the right controller. Right now I have next:

// Setup Router
$di->set('router', function(){

     $router = new \Phalcon\Mvc\Router(false);

     $router->removeExtraSlashes(true);

     $router->add('/', array(
        'namespace' => 'Controllers',
        'controller' => "login"
     ));

      $router->add('/:controller/:action/', array(
        'namespace' => 'Controllers',
        'controller' => 1,
        'action' =>2
     ));

      $router->add('/admin/:controller/:action/', array(
        'namespace' => 'Controllers\Admin',
        'controller' => 1,
        'action' =>2
     ));

     $router->add('/admin/users/:controller/:action/', array(
        'namespace' => 'Controllers\Admin\Users',
        'controller' => 1,
        'action' =>2
     ));

     return $router;
});

That will be also very big if I need to manually setup router for each sub-folder and namespace.

So the questions that I have are this:

  1. Is there any way to make a loader prettier and smaller? As it will grow bigger.
  2. How can I setup router so that I don't need to enter all of the namespaces and combinations of subfolders? Is there any way to make it smaller? May be modify dispatcher or any other class? Or is there a way I can set a path variable in the router to the location of the controller?

I have researched Phalcon documentation but could not find the way to do that.

Any help and suggestions are very much appreciated.

Thanks

1条回答
做自己的国王
2楼-- · 2019-05-02 00:38

Ad. 1. You can change your namespaces to be more PSR-0 (in my opinion), so I would make:

  • app
    • controllers
      • Admin
        • Users
          • UsersController.php

The you can register one namespace Admin or any other. Then you need to register only the top most namespace to work (keep in mind that your UsersController must have namespace Admin\Users\UsersController; to work). Thena autoloader should have only:

 $loader
    ->registerDirs(
        array(
            // It's taken from my config so path may be different
            __DIR__ . '/../../app/controllers/'
            // other namespaces here (like for models)
        )
    );

I'm using registerDirs so I only point loader to the folder in which some namespace exists.

Ad. 2.

For this you can use groups of routes so you can pass a namespace as a parameter for config array of constructor and then do the repeative task in one place. Then just create new instances with different parameters;

$router->addGroup(new MahGroup(array('namespace' => 'Mah\\Controller'));

So inside MahGroup class could be:

class MahGroup extends Phalcon\Mvc\Router\Group {
    public function _construct($config = array()) {
       $this->setPrefix('/' . $config['perfix']);
       $router->add('/:controller/:action/', array(
          'namespace' => $config['namespace'],
          'controller' => 1,
          'action' => 2
       ));
       // etc...
    }
}

And then configuring routes:

$router->addGroup( new MahGroup(array('prefix' => 'mah-namespace', 'namespace' => 'Mah\\Namespace' )) );
$router->addGroup( new MahGroup(array('prefix' => 'mah-other-namespace', 'namespace' => 'Mah\\Other\\Namespace' )) );

But given examples for second question are just what could be done. I usually create Group class for each namespace and then declare some routes that my app uses since I'm not using english names for routes and I need rewriting polish urls to controllers which have also some namespaces.

查看更多
登录 后发表回答