7

I am running Symfony 1.3.6 on Ubuntu 10.0.4 LTS.

I have written a Symfony task that generates a report which contains links (URLs).

Here is a snippet of the execute() method in my task class:

  protected function execute($arguments = array(), $options = array())
  {
    //create a context
    sfContext::createInstance($this->configuration);
    sfContext::getInstance()->getConfiguration()->loadHelpers(array('Url', 'Asset', 'Tag'));

    ...
    $url = url_for("@foobar?cow=marymoo&id=42");

    // Line 1
    echo '<a href="'.$url.'">This is a test</a>';

    // Line 2
    echo link_to('This is a test', $url); 
  }

The route name is defined like this:

foobar:
  url: /some/fancy/path/:cow/:id/hello.html
  param: {  module: mymodule, action: myaction }

When this is run, the generated link is:

Line 1 produces this output:

./symfony/symfony/some/fancy/path/marymoo/42/hello.html

instead of the expected:

/some/fancy/path/marymoo/42/hello.html

Line 2 generates an error:

Unable to find a matching route to generate url for params "array ( 'action' => 'symfony', 'module' => '.',)".

Again, the expected URL is:

/some/fancy/path/marymoo/42/hello.html

How may I resolve this?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
morpheous
  • 16,270
  • 32
  • 89
  • 120

4 Answers4

17

To generate a URL in a task:

protected function execute($arguments = array(), $options = array())
{
  $routing = $this->getRouting();
  $url = $routing->generate('route_name', $parameters);
}

We add a method to generate routing so that the production URL is always used:

   /**
   * Gets routing with the host url set to the url of the production server
   * @return sfPatternRouting
   */
  protected function getProductionRouting()
  {
    $routing = $this->getRouting();
    $routingOptions = $routing->getOptions();
    $routingOptions['context']['host'] = 'www.example.com';
    $routing->initialize($this->dispatcher, $routing->getCache(), $routingOptions);
    return $routing;
  }
Jeremy Kauffman
  • 10,293
  • 5
  • 42
  • 52
  • +1 for the nice, succinct snippet which shows me how to solve this problem. I shall modify the code slightly to suit what I am doing, test it, if it works, I'll accept this answer. – morpheous Jul 20 '10 at 07:03
  • Where should i put this snippet? I can't call $this->getRouting() from a task :/ – JavierIEH Oct 22 '12 at 14:00
  • You can use sfContext::getInstance()->getRouting() in a task. – Omn Nov 08 '12 at 00:41
3

I you wanna to use standard helpers (like url_for) to generate url, maybe this code could help you:

  protected function execute($arguments = array(), $options = array())
  {
    // initialize the database connection
...
$context = sfContext::createInstance($this->configuration);

$routing = $context->getRouting();
$_options = $routing->getOptions();
$_options['context']['prefix'] = "";// "/frontend_dev.php" for dev; or "" for prod
$_options['context']['host'] = sfConfig::get('app_url_base');
$routing->initialize($this->dispatcher, $routing->getCache(),$_options);
$context->getConfiguration()->loadHelpers('Partial');
$context->set('routing',$routing);    
//$_SERVER['HTTP_HOST'] = sfConfig::get('app_url_base'); // ---> I don't remember why I have this on my code, shouldn't be necessary
...

Then, you can use url_for function everywhere with absolute=true parameter magically working.

Of course, you need to add a *url_base* definition in your app.yml (or maybe you can leave it harcoded)

glerendegui
  • 1,457
  • 13
  • 15
  • 2
    thansk a lot, this worked for me. little comment: `$options` is used for the task command line options, so a different name for the variable avoids problems.. – Tapper Oct 30 '12 at 16:34
1

I have had the same problem and found the following Code Snippet: http://snippets.symfony-project.org/snippet/378

The solution is rather similar, however it extends the ProjectConfiguration. The advantage of this approach is, that it works transparently in modules as as well.

derflocki
  • 863
  • 1
  • 11
  • 19
0

You can tweak default request options for commands (sfTask) in the project configuration script config/ProjectConfiguration.class.php

class ProjectConfiguration extends sfProjectConfiguration {

    public function setup() {
        ...
        $this->dispatcher->connect('command.pre_command', array('TaskWebRequest', 'patchConfig'));
    }

}

class TaskWebRequest extends sfWebRequest {

    public function __construct(sfEventDispatcher $dispatcher, $parameters = array(), $attributes = array(), $options = array())
    {
        $options['no_script_name'] = true;
        $options['relative_url_root'] = '';
        parent::__construct($dispatcher, $parameters, $attributes, $options);
    }

    public static function patchConfig(sfEvent $event) {
        sfConfig::set('sf_factory_request', 'TaskWebRequest');
    }

}
Evgeniy Generalov
  • 1,296
  • 14
  • 26