0
votes

I want to route requests by processing http post vars, e.g. by putting and the like for "module", "controller", "action", etc., in a form, setting the action="..." target of the form to the application's default route and from there route to the module/controller/action route. The routes to module/controller/action shall not be accessible by the URL /module/controller/action, so the problem is, if the routes are configured in module.config.php, then they become accessible through the URL also? I may be missing a point there, it might be straightforward and simple, if only I knew the proper configuration for the routing in module.config.php, or is it necessary to set up an own custom routing service?

The redirect to route would reveal the route URL in the browser's address bar, and that is what I want to avoid, and don't know how.

if ($this->request->isPost()) {
    $post = $this->request->getPost();
    if (isset($post->module) && isset($post->controller) && isset($post->action)) {
        return $this->redirect()->toRoute($post->module, array(
            'controller' => $post->controller,
            'action' =>  $post->action
        ));
    } 
}

EDIT: Found half a solution: Use \Mvc\Controller\Plugin\Forward, like this:

in the application's default controller/action, calling a controller by its name as defined in the invokables section in the module.config.php, e.g. for a controller named 'register':

if ($this->request->isPost()) {
    $post = $this->request->getPost();
    if (isset($post->module) && isset($post->controller) && isset($post->action)) {
        return $this->forward()->dispatch('register', array('action' => $post->action));
    } 
}

Now I need to get the controller invokable name from the module/controller name as from the post vars. How?

1

1 Answers

0
votes

The key to the solution is to define unique controller invokable names in the modules' module.config.php's in a way that the controller invokable names can be constructed in a structured defined way, for example use the syntax "MyModule \ Controller \ MyController" for the invokables.

Example application:

modules/controllers:

  • Application
    • Index
  • User
    • Index
    • Login
    • Register

Code in file module/Application/config/module.config.php: (NB: Routes for application module still exist, so we can still have some pages that can be reached through URL routing, i.e. pages that we want to be reachable by search engines. If we want to get rid of these, too, then we have to set routing to type 'Hostname', as described in zf2 website with a single entry-point, no routes/paths in URL.)

return array(
    'controllers' => array(
        'invokables' => array(
            'Application\Controller\Index' => 'Application\Controller\IndexController',
        ),
    ),

    'router' => array(
        'routes' => array(
            'home' => array(
                'type' => 'Zend\Mvc\Router\Http\Literal',
                'options' => array(
                    'route'    => '/',
                    'defaults' => array(
                        '__NAMESPACE__' => 'Application\Controller',
                        'controller'    => 'Index',
                        'action'        => 'index',
                    ),
                ),
            ),
            'application' => array(
                'type'    => 'Literal',
                'options' => array(
                    'route'    => '/application',
                    'defaults' => array(
                        '__NAMESPACE__' => 'Application\Controller',
                        'controller'    => 'Index',
                        'action'        => 'index',
                    ),
                ),
                'may_terminate' => true,
                'child_routes' => array(
                    'default' => array(
                        'type'    => 'Segment',
                        'options' => array(
                            'route'    => '/[:controller[/:action]]',
                            'constraints' => array(
                                'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
                                'action'     => '[a-zA-Z][a-zA-Z0-9_-]*',
                            ),
                            'defaults' => array(
                            ),
                        ),
                    ),
                ),
            ),
        ),
    ),

If we want to suppress URL routing in module Application, too, then the routes in file module/Application/config/module.config.php should be defined as such:

'router' => array(
    'routes' => array(
        'home' => array(
            'type' => 'Hostname',
            'options' => array(
                'route'    => '4yougroup.local.f4u.0101',
                'defaults' => array(
                    '__NAMESPACE__' => 'Application\Controller',
                    'controller'    => 'Index',
                    'action'        => 'index',
                ),
            ),
        ),
    ),
),

Code in file module/User/config/module.config.php: (NB: No routes defined here!)

return array(
    'controllers' => array(
        'invokables' => array(
            'User\Controller\Index'     => 'User\Controller\IndexController',
            'User\Controller\Register'  => 'User\Controller\RegisterController',
            'User\Controller\Login'     => 'User\Controller\LoginController',
        ),
    ),

In order to route everything through the application's default route by using HTTP POST vars, put this code in the Application module's IndexController indexAction function:

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        if ($this->request->isPost()) {
            $post = $this->request->getPost();
            if (isset($post->module) && isset($post->controller) && isset($post->action)) {
                $controllerName = ucfirst($post->module) . "\\Controller\\" . ucfirst($post->controller);  

                return $this->forward()->dispatch($controllerName, array('action' =>  $post->action));
            } 
        }
    }
}

Then put HTML code like this in a view:

<form class="form-horizontal" action="" method="POST">
    <input type="hidden" name="module" value="user">
    <input type="hidden" name="controller" value="register">
    <input type="hidden" name="action" value="index">

...and voilĂ ...

If anyone could suggest a leaner and cleaner solution, would be nice :)