[英]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.