【问题标题】:Zend Framework 2 default moduleZend Framework 2 默认模块
【发布时间】:2013-02-20 08:20:54
【问题描述】:

在 ZF1 中,您不必在 URL 中包含模块;如果未提供,它将默认为...默认模块。这在 ZF2 中如何实现?我已经使用骨架应用程序来启动和运行,但似乎我总是需要包含模块名称,例如/application/controller/action.

我想我可以通过创建一个包含两个“占位符”的路线来解决这个问题;控制器和动作,然后将默认模块设置为“应用程序”。然后我会将其放入/config/autoload/global.php(或者可能是/config/application.config.php)中,以便该路由适用于我的所有应用程序。但是,即使我将路由硬编码为/user/index 之类的内容,我也会收到错误消息,即路由无法匹配 URL。

我尝试了下面的代码。

return array(
    'router' => array(
        'routes' => array(
            'nomodule' => array(
                'type' => 'Zend\Mvc\Router\Http\Literal',
                '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(
                        'module' => 'Application' // Not sure of the syntax here
                    )
                )
            ),
        )
    )
);

正如我在评论中所写的那样,我不确定我的问题是否与默认语法有关,但我认为如果我对路由进行硬编码并删除所有默认值,也会发生同样的情况。我还尝试根据骨架应用程序中的示例对其进行试验,但没有运气。我是不是走错了路?有更好的方法吗?还是我弄错了?

提前致谢。

编辑:有关使其工作的代码,请参阅答案。要了解它的工作原理,请阅读this article

【问题讨论】:

    标签: php zend-framework2


    【解决方案1】:

    注意:强烈建议使用显式路由而不是通配符。

    您在尝试中使用了 Zend\Mvc\Router\Http\Literal 路由类型,您可能猜到它是字面量,即完全匹配。要使其工作,您需要分段路线类型。

    Check application route in Zend Skeleton Application config 是子路由default。 它完全符合您的要求。

    至于模块 - 从您的代码角度来看,没有“模块”之类的东西。模块在启动时注册资源,此后不再相关。 在 zf2 中,您可以按类或别名指定确切的控制器,在该控制器下注册控制器管理器

    // module\Application\config\module.config.php
    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',
                        ),
                    ),
                    '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(
                                    'action' => 'index',
                                    '__NAMESPACE__' => 'Application\Controller'
                                )
                            )
                        )
                    )
                )
            )
        ),
        'controllers' => array(
            'invokables' => array(
                'Application\Controller\Index' => 'Application\Controller\IndexController',
                'Application\Controller\User' => 'Application\Controller\UserController'
            ),
        )
    );
    

    【讨论】:

    • 我会添加一个提示,即每个控制器都必须列在可调用对象中,以便将它们从 url 中解析出来,可调用对象中使用的符号必须与 url 中使用的符号匹配。
    • @SamuelHerzog 不需要在invokables,也可以配置为工厂。但是,是的,它必须在 ControllerManager 中。
    • 当然,但是由于您使用了可调用对象,我认为指出这一点比添加其他信息更有意义,那是您的任务:)
    • 感谢您的回答。我必须对代码进行一些小调整才能正常工作,但您为我指明了正确的方向。我已经编辑了您答案中的代码以反映我的编辑。我从段路由中删除了一个斜杠(因为它是/ 路由的子路由)并将__NAMESPACE__ 设置为我的控制器目录。通过这样做,我可以在 URL 中写入 localhost/user 并将其映射到 Application\Controller\User 而不必更改我的控制器键以匹配 URL 中的键(这样做会导致模块控制器冲突)。跨度>
    • 我希望这段代码可以使用以下 URL 集:/application/index/index; /application/index(默认操作); /application(控制器和动作是默认的); /index/index(模块是默认的); /index(模块和动作是默认的);但它没有......所以在我看来这不是正确的答案......当然我知道没有模块这样的东西,但是假设它们存在于路径中。
    【解决方案2】:

    正如我在@Xerkus 答案下的评论中所说,它不适用于所有 URL:

    /application/index/index
    /application/index
    /application
    /index/index
    /index
    /
    

    我还添加了testAction()IndexControllerTestController,其操作与IndexController 相同,因此我也可以在以下路线上测试我的解决方案:

    /index/test
    /test/index
    /test/test
    /test
    

    所以经过一些研究(主要是herehere),我准备了适用于所有人的解决方案。我将粘贴我的整个module.config.php 数组:

    return array(
        'router' => array(
            'routes' => array(
                'home' => array(
                    'type' => 'Literal',
                    'options' => array(
                        'route'    => '/',
                        'defaults' => array(
                            'controller' => 'Application\Controller\Index',
                            'action'     => 'index',
                        ),
                    ),
                ),
                'noModule' => 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(
                            '__NAMESPACE__' => 'Application\Controller',
                            '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(
            'factories' => array(
                'translator' => 'Zend\I18n\Translator\TranslatorServiceFactory',
            ),
        ),
        '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',
                'Application\Controller\Test' => 'Application\Controller\TestController'
            ),
        ),
        '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',
            ),
        ),
    );
    

    与 Zend 2 Skeleteon 应用程序配置相比,我添加了noModule 路由和新的controller invokable - test。当然noModule 路由包含Application/Controller 命名空间,所以基于这个事实,你可以设置任何你需要的默认模块。现在它可以正常工作了。

    当然请记住,您的noModule 路由应该在application.config.php 的第一个模块中定义,以确保它始终优先。还要记住,默认模块解决方案应该小心完成,以避免控制器和模块名称之间的冲突,例如如果您将下一个模块命名为Index,那么显然您将与Application 模块中的IndexController 发生命名冲突。

    【讨论】:

    • 虽然这可行,但它在概念上是错误的方法。您正试图在 zf2 应用程序中引入 zf1 的各个方面。在 zf2 中,特定路由受到强烈青睐,原因有很多,其中包括关注点分离:控制器/视图层中的代码将仅取决于路由名称,而不取决于路由名称 + 控制器 [+ 动作],因此控制器和/或动作可以很容易地在一个地方交换。您刚刚遇到的另一个问题是您的路由将错误地匹配大量 URI,从而导致控制器解析不正确和大量 WTF。
    • @Xerkus - 我同意你的观点,这不是它的本意,而是将 zf1 方法与 zf2 架构混合在一起。这就是为什么我写了你需要小心并寻找冲突的原因。我没有说我会在任何项目中使用它——我只是问了这个问题。有时您无法遵循最佳方法或设计模式,而且我知道,您作为开发人员以前也遇到过这种情况。这就是为什么我花了一些时间来使这段代码有效。正如我所写,我同意你的理论解释,这实际上帮助我理解了 ZF2 路由中的一些事情。
    【解决方案3】:

    总的来说,我是 ZF 的新手,刚开始学习它,所以尝试了这个,它对我有用。可以肯定的是,当您转到您的域 URL 并且不输入控制器名称时,您想更改您的默认模块,对吧?

    转到你的 module.config.php

     'router' => array(
        'routes' => array(
            'album WITH CONTROLLER IN URL' => array(
                'type'    => 'segment',
                'options' => array(
                    'route'    => '/album[/:action]',
                    'constraints' => array(
                        'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
                    ),
                    'defaults' => array(
                        'controller' => 'Album\Controller\Album',
                        'action'     => 'index',
                    ),
                ),
            ),
            'album WITHOUT CONTROLLER IN URL' => array(
                'type'    => 'segment',
                'options' => array(
                    'route'    => '/[:action]',
                    'constraints' => array(
                        'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
                    ),
                    'defaults' => array(
                        'controller' => 'Album\Controller\Album',
                        'action'     => 'index',
                    ),
                ),
            ),
            'SET IT AS YOUR HOMEPAGE' => array(
                'type'    => 'segment',
                'options' => array(
                    'route'    => '/',
                    'defaults' => array(
                        'controller' => 'Album\Controller\Album',
                        'action'     => 'index',
                    ),
                ),
            ),
        ),
    ),
    

    【讨论】:

    • 您的约束必须匹配路由中的占位符(例如 /:action)才能生效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-09
    • 1970-01-01
    • 2011-05-04
    • 2014-12-13
    相关资源
    最近更新 更多