How to effectively implement modules in an MVC environment and handle routing to multiple controllers in a single module?

I developed the basic structure of MVC as a training project in php - this is actually the second version, and I'm trying to improve two aspects that the first version did not justify:

  • Request routing: matching requests, for example. / controller / action / [params]
  • Modules: designed to expand the application, for example. CMS

This is where I am now:

  • I can take the request and parse it into different parts, e.g. controller, action, args, etc. These cards correspond to the corresponding controller classes / files. "/ foo / bar" → FooController :: bar () - all this is done in my RequestRouter class and encapsulated in the Request object.

    • I save a manifest object that contains files with a category (controllers, lib, etc.) for application files. The manifest is used by my autoloader method.
    • Since the manifest is cached, it is restored whenever I add new files / classes, this is true when new modules are added / removed.
  • Controller :: methods () perfectly displays the correct views.

  • Then come the modules, which are organized as the core is structured (/ Root / Raspberry / Producers / Kernel / Module)

Problem

The problem that I am thinking about at the moment is a combination of routing / request processing in which modules are considered:

  • If I ask for project.dev/admin, it will be mapped to AdminController :: index () - that’s correct.
  • However, when I reference project.dev/admin/editor, I still get AdminController :: editor () , where I really want EditorController :: index ()

After some research, I suppose I could create a Decorator that implements the Front Controller pattern and wraps this controller. The decorator can re-split the request to create / edit the controller and re-map the remaining segments (/ editor / action / args).

All this looks like it might work fine, but I feel like I am missing something fundamental earlier in the flow (RequestRouter). I am exploring other similar questions here in SO and reading on HMVC, and basically it seems like it can answer my questions, but it seems more interface oriented than with wireframe (if that makes sense?) Also looked at other Structures like Kohana, but I don’t quite understand how their modular system and routing to several controllers in one module work.

It would be very useful to evaluate any ideas or suggestions for the effective implementation of a modular system without introducing Front Controller or re-analyzing the request. Alternatively, if I have to restructure my modules differently, I would like to understand how to do it.

Additional Information:

My RequestRouter maintains a list of routes that I have predefined (including their default methods). Using these predefined routes, I can access / admin / editor and get EditorController :: index (), but I would need to determine the route for each controller and the request that goes to the controllers in the module. I do not think this is a good design. Here is an example of my routes:

Array ( [/foo] => Array ( [controller] => FooController [method] => bar [path] => /core ) [/admin] => Array ( [controller] => AdminController [method] => index [path] => /vendors/admin ) [/admin/editor] => Array ( [controller] => EditorController [method] => index [path] => /vendors/admin ) ) 

This is what my Request object looks like:

 Request Object ( [properties:Request:private] => Array ( [url] => /admin/editor [query] => [uri] => /admin/editor [controller] => admin [action] => editor [args] => [referrer] => Array ( [HTTP_REFERER] => [REMOTE_ADDR] => 127.0.0.1 [HTTP_VIA] => [HTTP_X_FORWARDED_FOR] => ) [get] => ) [request_status:Request:private] => 200 ) 

This is a sample of my manifest:

 [controller] => Array ( [icontroller] => /htdocs/raspberry/raspberry/core/controller/icontroller.class.php [index] => /htdocs/raspberry/raspberry/core/controller/index.php [serviceerror] => /htdocs/raspberry/raspberry/core/controller/serviceerror.controller.php [admin] => /htdocs/raspberry/raspberry/vendors/core/admin/controller/admin.controller.ph [composer] => /htdocs/raspberry/raspberry/vendors/core/admin/controller/composer.controller.php ) 

This is the application file system:

http://s11.postimage.org/pujb2g9v7/Screen_shot_2012_10_09_at_8_45_27_PM.png

+4
source share
1 answer

The problem seems to be caused by an overly simplified routing mechanism. It seems that you are using simple explode() to collect parameters from the URL. Although this only works in the basic examples, the installation will fail if you try to use more complex routing schemes.

Instead of dividing the string into / you should match it with regex patterns. Basically you define a list of patterns to match, and the first match is used to populate the Request instance.

In your situation, two patterns would be defined:

  • '#admin/(:?(:?/(?P<controller>[^/\.,;?\n]+))?/(?P<action>[^/\.,;?\n]+))?#'
  • '#(:?(:?/(?P<controller>[^/\.,;?\n]+))?/(?P<action>[^/\.,;?\n]+))?#'

If the first failed, the second will match.

PS . You should know that controllers should not output output. Response generation is the responsibility of viewing instances. Views must be fully functional objects that contain presentation logic and can constitute a response from several templates.

+3
source

Source: https://habr.com/ru/post/1438789/


All Articles