Using routes to generate URLs in a Symfony task
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.'">开发者_如何学Go;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?
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;
}
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)
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.
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');
}
}
精彩评论