如何在控制器外部创建Zend Framework控制器/操作URL?

时间:2011-02-09 00:00:06

标签: php zend-framework command-line

我使用zend框架1.11.2。我想创建可以在电子邮件文本中使用的控制器操作的URL。

在控制器中,我使用Zend_View_Helper_ServerUrl和Zend_View_Helper_Url这样做:

$serverUrlHelper = new Zend_View_Helper_ServerUrl();
$unsubscribeUrl = $serverUrlHelper->serverUrl(
    $this->getHelper('url')->url(
       array(
           'module' => $this->getFrontController()->getDefaultModule(),
           'controller' => 'newsletter',
           'action' => 'unsubscribe',
           'email' => $email
       ),
       'default',   // the route
       true));

现在我想这样做不是在控制器内,而是在命令行中。我已经设法按照此处描述的步骤Running a Zend Framework action from command line启动了zend控制器/操作。但是Application_Router_Cli没有assemble函数的实现。我从来没有用zend路由做过深刻的事情。有人可以请你给我一个如何实施它的提示吗?

4 个答案:

答案 0 :(得分:3)

我不确定default路由在application.ini中的含义,但我知道您的代码必须是这样的:

   $serverUrlHelper = new Zend_View_Helper_ServerUrl();
   $unsubscribeUrl = $serverUrlHelper->serverUrl(
    $this->getHelper('url')->url(
       array(
           'module' => $this->getFrontController()->getDefaultModule(),
           'controller' => 'newsletter',
           'action' => 'unsubscribe',
           'email' => $email
       ),
       null,   // the route 
       true));

因为您使用module , controller , view

数组手动分配路线

所以url视图帮助的第二个参数必须为null, 如果您在application.ini中有路线,并且您希望此链接遵循该路线,则您的功能必须如下:

 $serverUrlHelper = new Zend_View_Helper_ServerUrl();
   $unsubscribeUrl = $serverUrlHelper->serverUrl(
    $this->getHelper('url')->url(
        null,
       "email",   // aka the route name
       true));

希望我能以简单的方式解释它

答案 1 :(得分:1)

不是从Application_Router_Cli中的Zend_Controller_Router_Abstract进行子类化(如该教程中的指示),而是从Zend_Controller_Router_Rewrite中继承子类。这应该为您提供assemble()函数,并允许您使用URL Helper,就像在Web上下文中通常使用它一样。

答案 2 :(得分:1)

optima1's answer让我开始走上正轨,但我想分享一些额外的步骤,让url()serverUrl()视图助手在CLI脚本中运行。

检测环境

第一个挑战是定义服务器环境。这通常位于.htaccess或FastCGI环境变量中,因此它未在CLI中加载。我使用INI文件将服务器名称映射到环境。

[ServerEnvironments]
PROD-SERVER = "production"
STAGE-SERVER = "staging"
MY-LOCAL-VM = "development"

然后我的CLI脚本相应地设置APPLICATION_ENV常量。

$iniConfig = parse_ini_file(rtrim(dirname(__FILE__), '\/') . '/servers.ini', TRUE);
$environment = isset($iniConfig['ServerEnvironments'][getenv('COMPUTERNAME')])
             ? $iniConfig['ServerEnvironments'][getenv('COMPUTERNAME')]
             : 'production';
defined('APPLICATION_ENV') || define('APPLICATION_ENV', $environment);

填充服务器超全局

脚本的其余部分正常继续,如David's example所示。但是,我引导所有资源(对bootstrap()的空调)。我在实例化Zend_Application时还包含一个额外的INI文件,如下所示:

$application = new Zend_Application(
    APPLICATION_ENV,
    array('config' => array(APPLICATION_PATH . '/configs/application.ini',
                            APPLICATION_PATH . '/configs/cli.ini')));

CLI INI文件将存储通常由Web服务器提供的请求信息。

[production]
cli.request.serverVars.HTTPS = "on"
cli.request.serverVars.HTTP_SCHEME = "https"
; Host name, including port if non-standard.
cli.request.serverVars.HTTP_HOST = "example.com"
; Absolute path to the web root.  Exclude trailing slash.
cli.request.serverUrl = "https://example.com"
; Relative path from web root to the Zend Framework application.  Include leading slash.
cli.request.baseUrl = "/ZF"

[staging : production]
cli.request.serverUrl = "https://stage.example.com"
cli.request.serverVars.HTTP_HOST = "stage.example.com"

[development : production]
cli.request.serverUrl = "https://dev.example.com:4433"
cli.request.serverVars.HTTP_HOST = "dev.example.com:4433"

调用bootstrap()后,CLI脚本会填充$_SERVER超全局。请注意,在引导期间,我将应用程序配置存储在Zend_Registry

$config = Zend_Registry::get('config');
foreach($config->cli->request->serverVars as $name => $value) {
    $_SERVER[$name] = $value;
}

构建URI和调度

最后一个障碍是我使用自定义路由而不是/module/controller/action,后一种格式被禁用(Zend_Controller_Router_Rewrite::removeDefaultRoutes())。因此,CLI脚本需要指定路由而不是模块,控制器和操作。

$route = 'My/Custom/Route';

$spoofedUri = $config->cli->request->serverUrl
            . rtrim($config->cli->request->baseUrl, '/') . '/'
            . $route;
$request = new Zend_Controller_Request_Http($spoofedUri);
$request->setBaseUrl($config->cli->request->baseUrl);

$front = Zend_Controller_Front::getInstance();
$front->setRequest($request)
      ->setResponse(new Zend_Controller_Response_Cli())
      ->dispatch();

这可能无法解决网络和CLI请求之间的所有差异(您可能需要填充更多$_SERVER个变量),但我已修复url()serverUrl()

答案 3 :(得分:0)

在CLI脚本中,如果确保引导视图资源:

$application->getBootstrap()->bootstrap(array('db', 'mail', 'view'));

然后,您可以像往常一样使用相同的视图助手,对吗?