Question

I have a cron job which runs a ZF2 CLI route to send out some email notifications. The emails use an HTML view which I render via

$emailBody = $this->getServiceLocator()->get('viewrenderer')
               ->render('some/partial/name.phtml',$params);

Within this partial I use the view helper

<?php echo $this->url('some-route', array(), array('force_canonical' => true)); ?>

to generate an absolute URL to a page on my site. When I run this through a CLI however, I see an exception:

Zend\Mvc\Router\Exception\RuntimeException
Request URI has not been set

Do I need to inject a dummy HttpRequest object into the view rendering service or should I approach this a different way?

Was it helpful?

Solution

Because this is running through the CLI there's no real way for the script to know the correct domain to generate an absolute URI.

I ended up creating a view helper at module/Application/src/Application/View/Helper/CliDomain.php

<?php
namespace Application\View\Helper;
use Zend\View\Helper\AbstractHelper;

class CliDomain extends AbstractHelper {
    protected $_config_protocol;

    protected $_config_domain;

    public function __construct(array $cliConfig) {
        $this->_config_protocol = $cliConfig['scheme'];
        $this->_config_domain = $cliConfig['domain'];
    }

    public function __invoke() {
        return $this->_config_protocol.'://'.$this->_config_domain;
    }

}

and configured the factory in module/Application/config/module.config.php

return array(
    ...
    'view_helpers' => array(
        ...
        'cliDomain' => function ($sm) {
                $config = $sm->getServiceLocator()->get('config');
                if (!isset($config['cli_url'])) {
                    throw new \InvalidArgumentException('Please add a "cli_url" configuration to your project in order for cron tasks to generate emails with absolute URIs');
                }
                return new \Application\View\Helper\CliDomain($config['cli_url']);
            },

and in the project's config/autoload/global.php file I added a new key to the returned array

<?php
return array(
    ...
    'cli_config' => array(
        'scheme' => 'http',
        'domain' => 'prod.example.com',
    ),
);

for the staging server I added a matching config entry in config/autoload/local.php

<?php
return array(
    ...
    'cli_config' => array(
        'scheme' => 'http',
        'domain' => 'staging.example.com',
    ),
);

So in the question's view script I just prepended a call to the helper in the URL and don't bother forcing canonical.

<a href="<?php echo $this->cliDomain() . $this->url('some-route'); ?>">a link!</a>

OTHER TIPS

One way would be to pass in an Uri\Http object to the url() view helper:

<?php
// at the top of your view script, or passed assigned to the view model
$uri = new \Zend\Uri\Http('http://www.example.com/subdir');
?>


<!-- within the view script -->
<?= $this->url('some-route', array(),
    array('force_canonical' => true, 'uri' => $uri)); ?>

or just code it in the view script:

http://example.com/subdir<?= $this->url('some-route'); ?>

(I'm assuming you're using PHP5.4 or higher, so you can use <?=)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top