Php 链接中的ZF2路由无法正常工作
我正在开发一个Zend Framework 2应用程序,在这个应用程序中,我似乎无法正确路由,也不知道路由到哪里 我有一个主机名=>webapp.foo-bar.com。我们决定在末尾添加一个子标题=>/app/,该应用程序的名称为=>app。我在一个页面上有一个链接,它的路径应该是=>/graph/page name。但当我将鼠标悬停在链接上时,它看起来像:Php 链接中的ZF2路由无法正常工作,php,zend-framework,zend-framework2,config,standards,Php,Zend Framework,Zend Framework2,Config,Standards,我正在开发一个Zend Framework 2应用程序,在这个应用程序中,我似乎无法正确路由,也不知道路由到哪里 我有一个主机名=>webapp.foo-bar.com。我们决定在末尾添加一个子标题=>/app/,该应用程序的名称为=>app。我在一个页面上有一个链接,它的路径应该是=>/graph/page name。但当我将鼠标悬停在链接上时,它看起来像: <a href="/graph/page-name">FooBar</a> 我会得到webapp.foo-
<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(
),
),
),
);
如果两个应用共享同一个域,则您的配置无效。我的配置文件版本如下
另外,我创建了单独的模块示例,所以它不会干扰应用程序配置
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中,路由映射到特定的控制器类及其操作或方法,因此它们可以是任何模块。例如,此路由图形/页面名称
可以映射到图形控制器
及其方法pageNameAction()
。但这可以是任何其他控制器及其操作。这取决于你的需要
现在让我们来看看路线的类型。ZF中有一些路由插件。这些可用于指定管线的类型。例如,Hostname
指定域名和子域,如subdomain.domain.tld
。但是您使用的是domain.tld/v2/app
<代码>主机名
类型不允许在'route'=>'subdomain.domain.tld'
中使用/
。所以在这种情况下,这是行不通的
您可以获得这种类型的端点(domain.tld/v2/app
),而无需创建线程中所述的任何子域。这就是为什么MVC模式、框架更方便的原因。您可以在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
。这意味着如果我没有错的话,您希望从url中隐藏此部分v2/app
。但这仍然是一个挑战
如果在此v2/app/graph/page name
下使用了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
是它的子路由
现在您已经谈到了应该如何实现链接。如果您想将它们显示为菜单,则不必像您所说的那样编写代码。你可以。但请记住,在为导航构建数组时,为路由键提供值(路由的顶键)。
下面是此路由的上面示例图形/页面名称
[
'label' => 'Graph',
// route name not route pattern
'route' => 'graph', // not /graph/page-name
],
否则,如果要在页面正文中显示链接,请使用上面使用的$this->url()
帮助程序
有关Hostname
类型,请参阅此
如果我们无法在这里帮助您,请创建一个包含自己的url
实现的剪辑
/**
* @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);
有一种方法可以达到这个目的。你可以试试这个。要做到这一点,您需要创建一个自定义路由插件,然后将其设置为指向
Graph
控制器及其目标方法pageNameAction()
,在本例中。请按照以下步骤操作
这里的graph/page name
将作为v2/app/graph/page name
工作,这意味着以下链接将按照您的预期工作
<a href="/graph/page-name">FooBar</a>
现在将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');
希望这对你有帮助 谁拥有
图
控制器-主主机还是子主机?你到底想要什么?图形控制器属于子标题。我想做的主要事情是能够在应用程序的更高层配置href链接,如href=“/graph/page name”(单击该链接时,我会看到webapp.foo-bar.com/graph/page name),使其与webapp.foo-bar.com/v2/app/graph/page-name类似。希望我解释得更好一点,因为$this->url()方法不需要,因为大多数链接都是硬编码的。非常感谢您的帮助@jobaer感谢akond的回答。我回去工作后再试试看。是否所有链接都使用v2/应用程序?也应该在所有模块中进行更改,还是可以将应用程序模块更改为使用完整的链接更改来正确使用v2/app?我忘了只添加一行。请看我帖子的底部。啊,很酷,谢谢!是否需要该行才能创建链接?我需要链接保持原样,因为已经有许多链接使用href=“graph/page name”格式添加,我需要保持原样。希望能更改配置以添加v2/app更改。是否可以在不接触链接的情况下执行此操作?同时感谢您的时间:)如果graph/page name
移动到v2/app/graph/page name
,那么我恐怕答案是否定的:您必须点击所有这些链接。很抱歉延迟!这是一个信息量很大的回答。我想试试这个,也去zend论坛看看还有什么可以做的。另一种解决方案是虚拟H
<a href="/graph/page-name">FooBar</a>
'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',
],
],
],
],
],
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');