如何在ZF2中的控制台控制器中创建URL?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在ZF2中的控制台控制器中创建URL?相关的知识,希望对你有一定的参考价值。

我有一个控制台控制器和一个发送电子邮件的动作(在下面的module.config.php中定义)

'console' => array(
    'router' => array(
        'routes' => array(
            'cronroute' => array(
                'options' => array(
                    'route'    => 'sendEmails',
                    'defaults' => array(
                        'controller' => 'ApplicationControllerConsole',
                        'action' => 'send-emails'
                    )
                )
            ),              
        )
    )
),

在操作中,我想发送一封电子邮件,其中包含指向该网站上其他操作的链接。这通常使用URL View Helper来完成,但由于Request类型是Console而不是HTTP,因此不起作用。我试图创建一个HTTP请求,但我不知道如何给它站点域或Controller / Action链接。

我的控制器代码:

$vhm = $this->getServiceLocator()->get('viewhelpermanager');
$url = $vhm->get('url');
$urlString = $url('communication', array('action' => 'respond', 'id' => $id,
    array('force_canonical' => true));

这会引发错误:

======================================================================
   The application has thrown an exception!
======================================================================
ZendMvcRouterExceptionRuntimeException
Request URI has not been set

如何在具有站点方案,域和路径/到/ action的控制台控制器中创建HTTP请求?我如何将其传递给URL View Helper?

答案

以下是此问题的解决方法:

<?php

// Module.php

use ZendViewHelperServerUrl;
use ZendViewHelperUrl as UrlHelper;
use ZendUriHttp as HttpUri;
use ZendConsoleConsole;
use ZendModuleManagerFeatureViewHelperProviderInterface;

class Module implements ViewHelperProviderInterface
{

    public function getViewHelperConfig()
    {
        return array(
            'factories' => array(
                'url' => function ($helperPluginManager) {
                    $serviceLocator = $helperPluginManager->getServiceLocator();
                    $config = $serviceLocator->get('Config');

                    $viewHelper =  new UrlHelper();

                    $routerName = Console::isConsole() ? 'HttpRouter' : 'Router';

                    /** @var endMvcRouterHttpTreeRouteStack $router */
                    $router = $serviceLocator->get($routerName);

                    if (Console::isConsole()) {
                        $requestUri = new HttpUri();
                        $requestUri->setHost($config['website']['host'])
                            ->setScheme($config['website']['scheme']);
                        $router->setRequestUri($requestUri);
                    }

                    $viewHelper->setRouter($router);

                    $match = $serviceLocator->get('application')
                        ->getMvcEvent()
                        ->getRouteMatch();

                    if ($match instanceof RouteMatch) {
                        $viewHelper->setRouteMatch($match);
                    }

                    return $viewHelper;
                },
                'serverUrl' => function ($helperPluginManager) {
                    $serviceLocator = $helperPluginManager->getServiceLocator();
                    $config = $serviceLocator->get('Config');

                    $serverUrlHelper = new ServerUrl();
                    if (Console::isConsole()) {
                        $serverUrlHelper->setHost($config['website']['host'])
                            ->setScheme($config['website']['scheme']);
                    }

                    return $serverUrlHelper;
                },
            ),
        );
    }
}

当然,您必须在config中定义默认主机和方案值,因为无法在控制台模式下自动检测它们。

另一答案

我不敢相信,但我做到了:)

希望它能为你们所有人服务。

在使用fromRoute()函数的控制器中,我添加了以下行:

    $event  = $this->getEvent();
    $http   = $this->getServiceLocator()->get('HttpRouter');
    $router = $event->setRouter($http);
    $request = new endHttpRequest();
    $request->setUri('');
    $router = $event->getRouter();
    $routeMatch = $router->match($request);

    var_dump($this->url()->fromRoute(
                         'route_parent/route_child',
                         [
                            'param1' => 1,
                            'param2' => 2,
                         )
    );

输出:

//mydomain.local/route-url/1/2

当然route_parent / route_child不是控制台路由,而是HTTP路由:)

另一答案

感谢@Alexey Kosov的回复。当您的应用程序在域'/'之后在子目录而不是根目录下工作时,您可能会遇到问题。

你必须添加:

$router->setBaseUrl($config['website']['path']);

整码:

<?php

// Module.php

use ZendViewHelperServerUrl;
use ZendViewHelperUrl as UrlHelper;
use ZendUriHttp as HttpUri;
use ZendConsoleConsole;
use ZendModuleManagerFeatureViewHelperProviderInterface;

class Module implements ViewHelperProviderInterface
{

    public function getViewHelperConfig()
    {
        return array(
            'factories' => array(
                'url' => function ($helperPluginManager) {
                    $serviceLocator = $helperPluginManager->getServiceLocator();
                    $config = $serviceLocator->get('Config');

                    $viewHelper =  new UrlHelper();

                    $routerName = Console::isConsole() ? 'HttpRouter' : 'Router';

                    /** @var endMvcRouterHttpTreeRouteStack $router */
                    $router = $serviceLocator->get($routerName);

                    if (Console::isConsole()) {
                        $requestUri = new HttpUri();
                        $requestUri->setHost($config['website']['host'])
                            ->setScheme($config['website']['scheme']);
                        $router->setRequestUri($requestUri);
                        $router->setBaseUrl($config['website']['path']);
                    }

                    $viewHelper->setRouter($router);

                    $match = $serviceLocator->get('application')
                        ->getMvcEvent()
                        ->getRouteMatch();

                    if ($match instanceof RouteMatch) {
                        $viewHelper->setRouteMatch($match);
                    }

                    return $viewHelper;
                },
                'serverUrl' => function ($helperPluginManager) {
                    $serviceLocator = $helperPluginManager->getServiceLocator();
                    $config = $serviceLocator->get('Config');

                    $serverUrlHelper = new ServerUrl();
                    if (Console::isConsole()) {
                        $serverUrlHelper->setHost($config['website']['host'])
                            ->setScheme($config['website']['scheme']);
                    }

                    return $serverUrlHelper;
                },
            ),
        );
    }
}
另一答案

更新:这篇文章的正确答案可以在这里找到:Stackoverflow: Using HTTP routes within ZF2 console application

嗯,你非常接近这个,但你没有使用Url插件。如果您进一步深入了解控制器插件的ZF2文档,您可以找到解决方案。

参见:ZF2 Documentation - Controller plugins

您的ConsoleController必须实现以下之一,才能检索Controller插件:

  1. AbstractActionController
  2. AbstractRestfulController
  3. setPluginManager

好吧,如果你还没有完成,我建议用AbstractActionController扩展你的控制器。

如果您使用AbstractActionController,您可以简单地调用$urlPlugin = $this->url(),因为AbstractActionController有一个__call()实现为您检索插件。但你也可以使用:$urlPlugin = $this->plugin('url');

因此,为了生成邮件的URL,您可以在控制器中执行以下操作:

$urlPlugin = $this->url();
$urlString = $urlPlugin->fromRoute(
    'route/myroute',
    array(
        'param1' => $param1,
        'param2' => $param2
    ),
    array(
        'option1' => $option1,
        'option2' => $option2
    )
);

您现在可以将此URL传递给viewModel或在viewModel中使用URL viewHelper,但这取决于您。

尽量避免在控制器中使用viewHelpers,因为我们已经为这种情况提供了插件。

如果你想知道AbstractActionController有什么方法,这里是ZF2 ApiDoc - AbstractActionController

为了完成这项工作,您必须使用适当的结构设置路由配置:

// This can sit inside of modules/Application/config/module.config.php or any other module's config.
array(
    'router' => array(
        'routes' => array(
            // HTTP routes are here
        )
    ),

    'console' => array(
        'router' => array(
            'routes' => array(
                // Console routes go here
            )
        )
    ),
)

如果您有控制台模块,只需坚持使用控制台路径路径。不要忘记控制台键及其下方的所有路线!请查看文档以供参考:ZF2中的Zend Db如何控制事务?

如何在XCP中创建自定义窗口小部件

在控制器 .NET MVC 中创建 URL

@Url.Action 添加“amp;”在控制器中创建空值的参数之间?

如何在 Laravel Route 中创建两个或多个 url

在 CodeIgniter 控制器中创建函数