Routing in Zend Framework 2

2020-04-04 11:09发布

问题:

I'm trying to do some routing in Zend Framework 2, but it's not working.

The basics of the skeleton application are working, so I added a new module called User and the following code in the file \module\User\config\module.config.php

'controllers' => array(
    'invokables' => array(
        'User\Controller\User' => 'User\Controller\UserController',
    ),
),

'router' => array(
    'routes' => array(

        'login' => array(
            'type'    => 'Literal',
            'options' => array(
                'route'    => '/login',
                'defaults' => array(
                    '__NAMESPACE__' => 'User\Controller',
                    'controller'    => 'User',
                    'action'        => 'login',
                ),
            ),
        ),

        'user_create' => array(
            'type'    => 'Literal',
            'options' => array(
                'route'    => '/user/create',
                'defaults' => array(
                    '__NAMESPACE__' => 'User\Controller',
                    'controller'    => 'User',
                    'action'        => 'create',
                ),
            ),
        ),

    ),
),

If I try to access the first route (/login), it works.

But the second route (/user/create) results in the error:

File:

F:\www\ZendVendas\library\Zend\Mvc\Router\Http\TreeRouteStack.php:313

Message:

Route with name "create" not found

If I do create a route without the controller name, it works:

        'create' => array(
            'type'    => 'Literal',
            'options' => array(
                'route'    => '/create',
                'defaults' => array(
                    '__NAMESPACE__' => 'User\Controller',
                    'controller'    => 'User',
                    'action'        => 'create',
                ),
            ),
        ),

But I would want the route were "/user/create", and don't "/create".

I have searched for many topics, but can't see where is my mistake. Appreciate any help ;)

Edit: ajusted code with suggestions of @Jurian

'router' => array(
    'routes' => array(

        'user' => array(
            'type'    => 'Literal',
            'options' => array(
                'route'    => '/user',
                'defaults' => array(
                    'controller' => 'User\Controller\User',
                    'action'     => 'profile',
                ),
            ),


            'child_routes' => array(
                'login'  => array(
                    'type' => 'Literal',
                    'options' => array(
                        'route'    => '/login',
                        'defaults' => array(
                            'controller' => 'User\Controller\User',
                            'action'     => 'login',
                        ),
                    ),
                ),
                'create' => array(
                    'type' => 'Literal',
                    'options' => array(
                        'route'    => '/create',
                        'defaults' => array(
                            'controller' => 'User\Controller\User',
                            'action'     => 'create',
                        ),
                    ),
                ),
            ),
        ),

    ),
),

回答1:

You have to understand how routing works in Zend Framework 2. Routes have a name and some configuration. The structure looks as follows:

'router' => array(
  'routes' => array(
    'route_name_1' => array( /* config here */ ),
    'route_name_2' => array( /* config here */ ),
    'route_name_3' => array( /* config here */ ),
  ),
),

Here the route names are route_name_1 etc. If you assemble an url, you use that route name. So if route_name_1 has the url /foo/bar/baz, you can ask for the url of route_name_1 by using the url view helper:

echo $this->url('route_name_1'); // prints /foo/bar/baz

Your url /user/create is mapped to the route name user_create so to assemble this url, you need to pass on the route name:

echo $this->url('user_create'); // prints /user/create

CHILD ROUTES

There is also a concept of child routes. This can give you a route user which maps to /user and then this user route has a child create which maps to /create and as such the "total" route of create is /user/create. This can be configured as follows:

'router' => array(
  'routes' => array(
    'route_name_1' => array( /* config here */ ),
    'route_name_2' => array(
      /* config here */

      'child_routes' => array(
        'child_name_1' => array( /* config here */ ),
        'child_name_2' => array( /* config here */ ),
      ),
    ),
  ),
),

Now, if you want to assemble an url for route_name_2 it just looks as above:

echo $this->url('route_name_1');

But if you need to assemble the url for child_name_1 you construct a "path" with a / between the name and its parent(s):

echo $this->url('route_name_1/child_name_1');

So although you can access the /user/create route fine with the route name you already have, you might want to use child routes as this gives you a more flexible routing system:

'router' => array(
  'routes' => array(
    'user' => array(
      'type'    => 'Literal',
      'options' => array(
        'route'    => '/user/create',
          'defaults' => array(
            'controller' => 'User\Controller\User',
            'action'     => 'profile',
          ),
        ),
      ),

      'child_routes' => array(
        'login'  => array(
          'type' => 'Literal',
          'options' => array(
            'route'    => '/login',
            'defaults' => array(
              'action'     => 'login',
            ),
          ),
        ),
        'create' => array(
          'type' => 'Literal',
          'options' => array(
            'route'    => '/create',
            'defaults' => array(
              'action'     => 'create',
            ),
          ),
        ),
      ),
    ),
  ),
),

Then you have a route user which maps to a "profile". If you assemble user/create you go to /user/create and it uses the "createAction" from the user controller. The same hapens with user/login route.



回答2:

I have found what I was doing wrong.

In one of my view files, there was a URL function pointing to the route /create. It would be much helpful if Zend indicated the file with the invalid route, but, once I found the mistake, everything is working now.

'router' => array(
    'routes' => array(

        'login' => array(
            'type'    => 'Literal',
            'options' => array(
                'route'    => '/login',
                'defaults' => array(
                    'controller' => 'User\Controller\User',
                    'action'     => 'login',
                ),
            ),
        ),

        'logout' => array(
            'type'    => 'Literal',
            'options' => array(
                'route'    => '/logout',
                'defaults' => array(
                    'controller' => 'User\Controller\User',
                    'action'     => 'logout',
                ),
            ),
        ),

        'user' => array(
            'type'    => 'Literal',
            'options' => array(
                'route'    => '/user',
                'defaults' => array(
                    'controller' => 'User\Controller\User',
                    'action'     => 'profile',
                ),
            ),
            'child_routes' => array(
                'create' => array(
                    'type' => 'Literal',
                    'options' => array(
                        'route'    => '/create',
                        'defaults' => array(
                            'controller' => 'User\Controller\User',
                            'action'     => 'create',
                        ),
                    ),
                ),
                'edit' => array(
                    'type' => 'Literal',
                    'options' => array(
                        'route'    => '/edit',
                        'defaults' => array(
                            'controller' => 'User\Controller\User',
                            'action'     => 'edit',
                        ),
                    ),
                ),
            ),
        ),      

    ),
),

Thank you for the help!