Маршрутизатор zf2: один модуль не позволяет маршрутизатору найти другой модуль. Как я могу заставить оба работать?

Мы только начинаем с zf2, поэтому кто-то еще сделал модуль сервера миниатюр, а затем я добавил модуль сервера поиска. Я называю эти серверы, потому что они оба RESTful apis. Первоначально они, казалось, работали вместе, но кто-то внес некоторые изменения в мой модуль, и теперь сервер миниатюр не будет работать, если Lookup не будет удален из application.config.php список модулей. Сервер поиска работает независимо. Просматривая код, я не вижу, как изменения, внесенные в 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',
        ),
    ),
);

Как видите, есть начальный модуль Album и несколько других экспериментальных. Модуль My Lookup использует превосходный модуль AP_XmlStrategy от Allessandro Pietrobelli.

Ниже миниатюра 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',
        ),
    ),
);

И поиск 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',
        ),
    ),
);

Здесь есть какие-то очевидные ошибки, которые я пропускаю?

1 ответ

Решение

Запросы могут соответствовать нескольким маршрутам. Пример: 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], это начинается с буквальной части. Тогда у вашего второго модуля (Lookup) есть маршрут [/:action][/:version][/:resource][/:code][/:resource_xref],

Теперь, если вы вернетесь к заказу LIFO, любой маршрут, начинающийся с /thumbnail будет соответствовать уже на пути поиска.

Решение

Есть два варианта. Сначала поменяйте порядок модулей. Это всегда важный порядок, если у вас есть взаимозависимые отношения между модулями. Сначала загрузите Lookup, а затем Thumnnail, чтобы маршрут миниатюры был помещен позже в конфигурацию. Таким образом, это соответствует в первую очередь. Таким образом, ваше приложение снова работает.

Тогда есть второе решение (и imho, тем лучше). У вас есть "один путь, чтобы управлять ими всеми" в 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] полностью отделен от маршрутов поиска.

Другие вопросы по тегам