问题
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?
回答1:
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;
}
回答2:
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)
回答3:
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.
回答4:
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');
}
}
来源:https://stackoverflow.com/questions/3285953/using-routes-to-generate-urls-in-a-symfony-task