3

我们刚开始使用 zf2,所以别人做了一个缩略图服务器模块,然后我添加了一个查找服务器模块。我称这些服务器是因为它们都是 RESTful api。最初它们似乎可以一起工作,但有人对我的模块进行了一些更改,现在缩略图服务器将无法工作,除非从application.config.php模块列表中删除 Lookup。查找服务器无论如何都可以工作。查看代码,我看不出对 Lookup 所做的更改会如何影响 Thumbnail。我得到的错误如下所示:

<h1>A 404 error occurred</h1>
<h2>Page not found.</h2>
<p>The requested controller was unable to dispatch the request.</p>
<dl>
<dt>Controller:</dt>
<dd>Lookup\Controller\Lookup</dd>
</dl>

如下application.config.php所示:

<?php
return array(
    'modules' => array(
        'Application',
        'SanRestful',
        'Album',
        'AlbumRest',   
        'Thumbnail',         
        'Lookup',
        'AP_XmlStrategy',
    ),
    'module_listener_options' => array(
        'config_glob_paths'    => array(
            'config/autoload/{,*.}{global,local}.php',
            'config/autoload/{,*.}' . (getenv('APPLICATION_ENV') ?: 'production') . '.php',
        ),
        'module_paths' => array(
            './module',
            './vendor',
        ),
    ),
);

如您所见,这里有最初的专辑模块,还有一些其他的实验性模块。我的 Lookup 模块使用了Allessandro Pietrobelli 的优秀 AP_XmlStrategy 模块

下面是缩略图module.config.php。它有一个可能没有被使用的约束,因为没有称为“id”的参数,但这不应该把事情搞砸,不是吗?

<?php
return array(
    'controllers' => array(
        'invokables' => array(
            'Thumbnail\Controller\Thumbnail' => 'Thumbnail\Controller\ThumbnailController',
        ),
    ),

    // The following section is new and should be added to your file
    'router' => array(
        'routes' => array(
            'thumbnail' => array(
                'type'    => 'segment',
                'options' => array(
                    'route'    => '/thumbnail[/:action][/:output]',
                    'constraints' => array(
                        'id'     => '[0-9]+',
                    ),
                    'defaults' => array(
                        'controller' => 'Thumbnail\Controller\Thumbnail',
                        'action'     => 'index',
                    ),
                ),
            ),
        ),
    ),

    'view_manager' => array(
        'template_path_stack' => array(
            'thumbnail' => __DIR__ . '/../view',
        ),
    ),
);

和 Lookup module.config.php,标识符被混淆:

<?php
return array(
    'db' => array(
        'driver'         => 'Pdo',
        'dsn'            => 'pgsql:dbname=<dbname>;host=<host>;port=<port>',
        'username'       => '<username>',
        'password'       => '<password>',
        ),
    'service_manager' => array(
        'factories' => array(
            'Zend\Db\Adapter\Adapter'
                    => 'Zend\Db\Adapter\AdapterServiceFactory',
        ),
        'aliases' => array(
            'db' => 'Zend\Db\Adapter\Adapter',
        ),
    ),
    'controllers' => array(
        'invokables' => array(
            'Lookup\Controller\Lookup' => 'Lookup\Controller\LookupController',
        ),
    ),
    // The following section is new and should be added to your file
    'router' => array(
        'routes' => array(
            'lookup' => array(
                'type'    => 'segment',
                'options' => array(
                    'route'    => '[/:action][/:version][/:resource][/:code][/:resource_xref]',
                    'constraints' => array(
                        'action'         => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'version'        => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'resource'       => '[a-zA-Z][a-zA-Z0-9_-|\.]*',
                        'code'           => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'resource_xref'  => '[a-zA-Z][a-zA-Z0-9_-|\.]*',
                    ),
                    'defaults' => array(
                        'controller' => 'Lookup\Controller\Lookup',
                        'action'     => 'index',
                    ),
                ),
            ),
        ),
    ),
    'view_manager' => array(
        'template_path_stack' => array(
            'lookup' => __DIR__ . '/../view',
        ),
        'strategies' => array(
            'ViewJsonStrategy',
            'ViewXmlStrategy',
        ),
    ),
);

这里有我遗漏的明显错误吗?

4

1 回答 1

5

请求可以由多个路由匹配。一个例子: url /foo 可以通过文字路由匹配,也可以通过路由/foo匹配[/:action]。要区分这两条路由,配置它们的顺序很重要

会发生什么,路由按LIFO顺序匹配,所以最后一个路由必须是最显式的。在“/foo”示例中,此配置将匹配文字:

'router' => array(
    'routes' => array(
        'test1' => array(
            'type'    => 'segment',
            'options' => array(
                'route'    => '[/:action]',
                'defaults' => array(
                    //
                ),
            ),
        ),
        'test2' => array(
            'type'    => 'literal',
            'options' => array(
                'route'    => '/foo',
                'defaults' => array(
                    //
                ),
            ),
        ),
    ),
),

但是,在下面的配置中,文字永远不会被匹配,因为[/:action]它可能匹配/foo.

'router' => array(
    'routes' => array(
        'test2' => array(
            'type'    => 'literal',
            'options' => array(
                'route'    => '/foo',
                'defaults' => array(
                    //
                ),
            ),
        ),
        'test1' => array(
            'type'    => 'segment',
            'options' => array(
                'route'    => '[/:action]',
                'defaults' => array(
                    //
                ),
            ),
        ),
    ),
),

现在看看你的两个模块。第一个(缩略图)有一条路线/thumbnail[/:action][/:output]。它以文字部分开头。然后你的第二个模块(查找)有一个 route [/:action][/:version][/:resource][/:code][/:resource_xref]

现在,如果您回到 LIFO 顺序,任何以 开头的路由/thumbnail都将在 Lookup 路由中匹配。

解决方案

有两种选择。首先是交换模块的顺序。如果模块之间存在相互依赖的关系,这始终是一个重要的顺序。先加载 Lookup,然后再加载 Thumnnail,因此缩略图路径稍后会放在配置中。因此,它首先匹配。因此,您的应用程序再次运行。

然后是第二个解决方案(恕我直言,更好)。在 Lookup 中有“一条规则来统治它们”,这不是一个很好的做法。您可能会像现在一样陷入麻烦,不知道出了什么问题。因此,在您的路线中尽可能多地指定。使 Lookup 的第一部分也是字面的(/lookup[/:action][/:version][/:resource][/:code][/:resource_xref]不是一个选项吗?)。或删除动作作为参数并制作这些文字:

'router' => array(
    'routes' => array(
        'view' => array(
            'type'    => 'segemnt',
            'options' => array(
                'route'    => '/view[/:version][/:resource][/:code][/:resource_xref]',
                'defaults' => array(
                    'action' => 'view',
                    //
                ),
            ),
        ),
        'create' => array(
            'type'    => 'segment',
            'options' => array(
                'route'    => '/create[/:version][/:resource][/:code][/:resource_xref]',
                'defaults' => array(
                    'action' => 'create',
                    //
                ),
            ),
        ),
        'update' => array(
            'type'    => 'segment',
            'options' => array(
                'route'    => '/update[/:version][/:resource][/:code][/:resource_xref]',
                'defaults' => array(
                    'action' => 'update',
                    //
                ),
            ),
        ),
        // And so on
    ),
),

这样,您的查找模块有一个固定的起点,并且仅当这些第一部分在请求 uri 中时才匹配。然后,您/thumbnail[/:action][/:output]将与 Lookup 路线完全脱钩。

于 2013-04-27T11:16:11.590 回答