4

I use the zend framework 1.11.2. I want to create URLs to controller actions that can be used inside email texts.

Within controllers I have done that with Zend_View_Helper_ServerUrl and Zend_View_Helper_Url like this:

$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));

Now I want to do this not within a controller but instead from command line. I already managed to start a zend controller/action by following the steps described here Running a Zend Framework action from command line. But the Application_Router_Cli does not have an implementation for the assemble function. I never have done something deeply with zend routing. Could anyone could please give me an hint how to implement it?

Community
  • 1
  • 1
Marc
  • 1,900
  • 14
  • 22

4 Answers4

3

I am not sure what default routes means in your application.ini but i know your code must be like this :

   $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));

since your are assmble the route manually by using array of module , controller , view

so the second param of the url view help must be null , and in the case you have a route in your application.ini and you want this link to follow that route your function must be like this :

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

hopefully i explain it in easy way

tawfekov
  • 5,084
  • 3
  • 28
  • 51
1

Instead of sub-classing from Zend_Controller_Router_Abstract in Application_Router_Cli (as instructed in that tutorial), subclass from Zend_Controller_Router_Rewrite. This should give you the assemble() function and allow you to use the URL Helper as you would normally use it in a web context.

msun
  • 761
  • 4
  • 8
1

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.

Community
  • 1
  • 1
WimpyProgrammer
  • 628
  • 8
  • 10
0

In your CLI script, if you make sure to bootstrap a view resource:

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

then, you can use the same view helpers as always, right?

David Weinraub
  • 14,144
  • 4
  • 42
  • 64