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?

4 Answers 4

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

Sign up to request clarification or add additional context in comments.

Comments

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.

Comments

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.

Comments

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?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.