zend-frameworkrouteszend-framework2zend-framework-mvczend-framework-routing

Zend Framework 2 routing error: resolves to invalid controller class or alias


I'm trying to learn Zend Framework 2 and I have their skeleton application up and running. In order to access it I visit http://localhost:8080/. When visiting that link it displays their generic Zend page. What I want to be able to do is visit http://localhost:8080/application/test and have it bring me to a different page with a different layout.

Here is the module.config.php

<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'router' => array(
        'routes' => array(
            'home' => array(
                'type' => 'Zend\Mvc\Router\Http\Literal',
                'options' => array(
                    'route'    => '/',
                    'defaults' => array(
                        'controller' => 'Application\Controller\Index',
                        'action'     => 'index',
                    ),
                ),
            ),
            // The following is a route to simplify getting started creating
            // new controllers and actions without needing to create a new
            // module. Simply drop new controllers in, and you can access them
            // using the path /application/:controller/:action
            '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(
                            ),
                        ),
                    ),
                ),
            ),
        )
    ),
    'service_manager' => array(
        'abstract_factories' => array(
            'Zend\Cache\Service\StorageCacheAbstractServiceFactory',
            'Zend\Log\LoggerAbstractServiceFactory',
        ),
        'aliases' => array(
            'translator' => 'MvcTranslator',
        ),
    ),
    'translator' => array(
        'locale' => 'en_US',
        'translation_file_patterns' => array(
            array(
                'type'     => 'gettext',
                'base_dir' => __DIR__ . '/../language',
                'pattern'  => '%s.mo',
            ),
        ),
    ),
    'controllers' => array(
        'invokables' => array(
            'Application\Controller\Index' => 'Application\Controller\IndexController'
        ),
    ),
    'view_manager' => array(
        'display_not_found_reason' => true,
        'display_exceptions'       => true,
        'doctype'                  => 'HTML5',
        'not_found_template'       => 'error/404',
        'exception_template'       => 'error/index',
        'template_map' => array(
            'layout/layout'           => __DIR__ . '/../view/layout/layout.phtml',
            'application/index/index' => __DIR__ . '/../view/application/index/index.phtml',
            'error/404'               => __DIR__ . '/../view/error/404.phtml',
            'error/index'             => __DIR__ . '/../view/error/index.phtml',
        ),
        'template_path_stack' => array(
            __DIR__ . '/../view',
        ),
    ),
    // Placeholder for console routes
    'console' => array(
        'router' => array(
            'routes' => array(
            ),
        ),
    ),
);

In order to make it work for me this is what I tried:

First I created a controller named TestController in Application/src/Application/Controller/.

Next I added 'application/test/index' => DIR . '/../view/application/test/index.phtml' to the template_map array in view_manager.

I also added 'Application\Controller\Test' => 'Application\Controller\TestController' to the controllers array.

When I visit http://localhost:8080/application/test I get the error: test(resolves to invalid controller class or alias: test)

I'm obviously doing something wrong but tbh the documentation on Zend is not newb friendly at all and it's becoming very frustrating. Could someone point me in the correct direction? There's just so much configuration that I'm sure I'm missing something small. Thanks!


Solution

  • At the moment the route named application (the parent) defines a URL route of /application. The child route default however requires the controller name to be passed in as the first argument, followed by action.

    This means the URL would be

    /application/[:controller]/[:action]
    

    So visting

    /application/test
    

    You are inadvertently trying to fetch the 'test' controller; hence the error.

    Resolves to invalid controller class or alias : test

    To resolve this I would strongly recomend against using the a :controller route parameter but instead use a route per controller action.

    'application' => [
        'type' => 'Literal',
        'options' => [
            'route' => '/application',
            'defaults' => [
                'controller' => 'Application\Controller\Index',
                'action'     => 'index',
            ],
            'may_terminate' => true,
            'child_routes' => [
    
                'test' => [
                    'type' => 'Literal',
                    'options' => [
                        'route' => '/test',
                        'defaults' => [
                            // controller value is inherited from parent!
                            'action' => 'test', 
                        ],
                    ],
                ],
    
            ],
        ],
    ],