簡體   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