繁体   English   中英

链路中的ZF2路由无法正常工作

[英]ZF2 routing in links not working correctly

我正在研究Zend Framework 2应用程序的工作,我似乎无法正确路由或知道在哪里路由它。

我有一个Hostname => webapp.foo-bar.com。 我们决定在末尾添加一个Subhost => / app /,这个应用程序的名称叫做=> app。 我在页面上有一个链接,它的路由是=> / graph / page-name。 但当我将鼠标悬停在看起来像这样的链接上时:

<a href="/graph/page-name">FooBar</a>

我得到webapp.foo-bar.com/graph/page-name而不是webapp.foo-bar.com/app/graph/page-name。

我的应用程序配置是:

<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/ZendSkeletonApplication for the canonical source repository
 * @copyright Copyright (c) 2005-2013 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' => 'hostname',
                'options' => array(
                    'route'    => 'webapp.foo-bar.com/app',
                    '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(
    '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(
        ),
    ),
),
);

我看到有一个选项,如:

<a href="<?=$this->url('application/default', array('controller' => 'graph', 'action' => 'page-name')?>">FooBar</a>

这需要在每个链接上完成,还是我们能够在配置级别完成?

谢谢!


更新:

我已经设法让客户端使用this-> url()方法,事情看起来很好。 即使在jQuery部分,链接也在起作用。 我有一个关于链接到另一个控制器没有显示链接中的操作的小问题。

<a href="<?php echo $this->url('foo-bar', array('action' => 'bar-foo'))?>?year=2015"</a>

带回webapp.foo-bar.com/app/foo-bar?year=2015。 我希望它返回webapp.foo-bar.com/app/foo-bar/bar-foo?year=2015。 这是foo-bar控制器中的配置还是可以在this-url()中完成?

万分感谢所有帮助。 真的很适合它!

如果两个应用共享同一个域,则您的配置无效。 我的配置文件版本如下。

PS我创建了单独的模块Sample,因此它不会干扰Application配置。

use Zend\Router\Http\Literal;
use Zend\Router\Http\Segment;
use \Sample\Controller\IndexController;
use Zend\ServiceManager\Factory\InvokableFactory;


return [
    'router' => [
        'routes' => [
            'v2' => [
                'type' => Segment::class,
                'options' => [
                    'route' => '/v2/app',
                    'defaults' => [
                        'controller' => IndexController::class,
                        'action' => 'index',
                    ],
                ],
                'child_routes' => [
                    'index' => [
                        'type' => Literal::class,
                        'options' => [
                            'route' => '/',
                            'defaults' => [
                                'controller' => IndexController::class,
                                'action' => 'index',
                            ],
                        ],
                    ],
                    'application' => [
                        'type' => Segment::class,
                        'options' => [
                            'route' => '[/:action]',
                            'defaults' => [
                                'controller' => IndexController::class,
                                'action' => 'index',
                            ],
                        ],
                    ]
                ],
            ],
        ],
    ],
    'controllers' => [
        'factories' => [
            IndexController::class => InvokableFactory::class,
        ],
    ],
    'view_manager' => [
        'template_path_stack' => [
            __DIR__ . '/../view',
        ],
    ],
];

这是您创建该应用程序的链接的方法:

<?php echo $this->url("v2/application", ['action' => 'page-name']) ?>

在ZF2中,路由映射到特定的控制器类及其操作或方法,因此它们可以是任何模块。 例如,此路由graph/page-name可以映射到GraphController及其方法pageNameAction() 但那可以是任何其他控制器及其动作。 这取决于您的需求。

现在让我们来看一个路线的类型。 ZF中有一些路由插件。 这些可用于指定路线的类型。 例如, Hostname指定域名和子域名,如subdomain.domain.tld 但您使用的是domain.tld/v2/app Hostname类型不允许/'route' => 'subdomain.domain.tld' 在这种情况下,这不起作用。

您可以获得此类型的端点( domain.tld/v2/app ),而无需创建您在线程中说明的任何子域。 这就是为什么MVC模式,Framework更方便。 您可以在ZF应用程序中为不同目的创建许多端点( domain.tld/v1/abc domain.tld/v2/mno domain.tld/v3/xyz等)。 它们可以映射到不同模块的不同控制器和动作。 所以你不需要像你问的那样依赖子域。

你还说你需要domain.tld/graph/page-name ,它实际上是domain.tld/v2/app/graph/page-name 这意味着如果我没有错,你想要从网址隐藏这部分v2/app 但这仍然是一个挑战。

如果您有它graph/page-name下此使用v2/app/graph/page-name ,你可以如下定义您的路线

// Top key of a route
'v2app' => [
    'type' => 'Segment',
    'options' => [
        'route' => '/v2/app',                   
        'defaults' => [
            '__NAMESPACE__' => 'Application\Controller',
            'controller'    => 'Index',
            'action'        => 'index',
        ],
    ],
    'may_terminate' => true,
    'child_routes' => [
        'default' => [
            'type' => 'Segment',
            'options' => [
                'route' => '/',
                'defaults' => [
                    'controller' => 'Application\Controller\Index',
                    'action' => 'index',
                ],
            ],
        ],                              
        'graph' => [
            'type' => 'Segment',
            'options' => [
                'route' => '[/:controller/:action]',
                'defaults' => [
                    'controller' => 'Application\Controller\Graph',
                    'action' => 'pageName',
                ],
            ],
        ],
    ],
],

您可以通过更正模块名称,控制器名称等将其添加到任何module.config.php的任何路由部分。但请记住,多个路由的相同配置会让您不高兴

现在输出这些路由使用以下代码片段

echo $this->url('v2app/graph', [], [], true);
echo $this->url(null, ['controller' => 'graph', 'action' => 'page-name']);

// outputs
// /v2/app/graph/page-name

v2app是你的顶级路由键,而graph是它的子路由。

现在您已经说过如何实现链接了。 如果您想将它们显示为菜单,则不必像您所说的那样编写代码。 您可以按照此操作将链接实现为菜单 但请记住,在为导航构建阵列时为路径键提供值(路线的顶部键)。 以下示例来自此路线graph/page-name

[
    'label' => 'Graph',
    // route name not route pattern
    'route' => 'graph', // not /graph/page-name
],

否则,如果要在页面正文中显示链接,则使用上面使用的$this->url()帮助程序。

请参阅此DOC获取Hostname类型。

如果我们在这里无法帮助您,请在此处提出

只需创建一个包含自己的url实现的cutomized ViewModel

/**
 * @param  \Zend\Mvc\MvcEvent $e The MvcEvent instance
 * @return void
 */
public function setLayout($e)
{
    // Should return your customization
    $viewModel = $e->getViewModel();

在这种情况下,所有$this->url()将直接执行相同的操作:

$this->url('application/default', array('controller' => 'graph', 'action' => 'page-name')

作为自定义渲染的部分示例:

$customStrategy = $app->getServiceManager()->get('{Your class name}'); 
$view->getEventManager()->attach($customStrategy, 1); // 1 - means priority

在你的课堂里

preg_replace_callback('/<a href=\\"([^\\"]*)\\">(.*)<\\/a>/iU', function ($matches) {
    // do whatever you need for each URL
}, $content);

或者它可以使用DOM对象(但它依赖于您的代码有效性):

$xpath = new \DOMXPath((new \DOMDocument)->loadHTML($content));
foreach ($xpath->query('//a[href]') as $link) {
    // ...
}

为此目的有一种方法。 你可以试试这个。 为此,您需要创建一个自定义路由插件,然后将其设置为路由指向Graph控制器及其目标方法pageNameAction() ,在本例中。 请按照以下步骤操作。

这里graph/page-name可以作为v2/app/graph/page-name这意味着以下链接可以按预期工作。

<a href="/graph/page-name">FooBar</a>

请从这里获取自定义路由插件。 使用名称空间YourModuleName\\Route将它放在此src/YourModuleName/Route目录下。

请注意,您需要将'template_prefix' => 'yourmodulename',替换为您自己的模块名称和所有小写字母。 将通过在场景后面匹配此模式yourmodulename/controller/action-name来搜索视图模板。

'v2app' => [
    'type' => 'Segment',
    'options' => [
        'route' => '[/v2/app]',             
        'defaults' => [
            'controller' => 'YourModuleName\Controller\Index',
            'action' => 'index',
        ],
    ],
    'may_terminate' => true,
    'child_routes' => [                         
        'graph' => [

            // We call the custom route plugin thus  
            'type' => 'YourModuleName\Route\AppRoute',
            'options' => [
                'dir_name'         => __DIR__ . '/../view',
                'template_prefix'  => 'yourmodulename',
                'filename_pattern' => '/[a-z0-9_\-]+/',                     
                'defaults' => [
                    'controller' => 'YourModuleName\Controller\Graph',
                    'action' => 'pageName',
                ],
            ],
        ],
    ],
],

现在格式化pageNameAction()如下

public function pageNameAction()
{
    // Get path to view template from route params
    $pageTemplate = $this->params()->fromRoute('page', null);

    // If path is not valid
    if($pageTemplate == null) {
        $this->getResponse()->setStatusCode(404); 
        return;
    }       

    $viewModel = new ViewModel();

    // Here we set template to be rendered for `v2/app/graph/page-name`
    $viewModel->setTemplate($pageTemplate);

    return $viewModel;
}

如果需要在视图脚本中输出链接,请使用这种方式

echo $this->serverUrl('/graph/page-name');

希望这会对你有所帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM