optima1's answer got me started on the right track but I wanted to share some additional steps I needed to make the url()
and serverUrl()
view helpers work in a CLI script.
Detect Environment
The first challenge is defining the server environment. This is often in the .htaccess or a FastCGI environment variable, so it's not loaded in the CLI. I use an INI file to map the server name to the environment.
[ServerEnvironments]
PROD-SERVER = "production"
STAGE-SERVER = "staging"
MY-LOCAL-VM = "development"
Then my CLI script sets the APPLICATION_ENV
constant accordingly.
$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);
Populate Server Superglobal
The rest of the script continues normally as shown in David's example. However, I bootstrap all resources (an empty call to bootstrap()
). I also include an additional INI file when instantiating Zend_Application
, like so:
$application = new Zend_Application(
APPLICATION_ENV,
array('config' => array(APPLICATION_PATH . '/configs/application.ini',
APPLICATION_PATH . '/configs/cli.ini')));
The CLI INI file will store request information that is normally provided by the web server.
[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"
After the call to bootstrap()
, the CLI script populates the $_SERVER
superglobal. Note that during bootstrapping, I store the application config in the Zend_Registry
.
$config = Zend_Registry::get('config');
foreach($config->cli->request->serverVars as $name => $value) {
$_SERVER[$name] = $value;
}
Build URI and Dispatch
The last hurdle is that I use custom routes instead of /module/controller/action
, and the latter format is disabled (Zend_Controller_Router_Rewrite::removeDefaultRoutes()
). So the CLI script needs to specify the route rather than the module, controller, and action.
$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();
This may not solve every discrepancy between web and CLI requests (you may need to populate more $_SERVER
variables) but it fixed url()
and serverUrl()
for me.