How to use absolute path in twig functions
SymfonyRoutingTwigSymfony Problem Overview
I have an application with Symfony2 (2.2). When I want to send a mail, I'm having trouble with the paths, which are all relative paths and obviously aren't working inside emails
for rendering the paths I'm using:
<a href="{{ path('route_name', {'param' : value}) }}">A link</a>
and for assets:
<img src="{{ asset('bundle/myname/img/image.gif') }}" alt="Title"/>
The previous examples work fine but the paths are relative therefore I need to append the domain. I can do something like:
<a href="http://domain.com{{ path('route_name', {'param' => param1}) }}">A link</a>
but this is not the best solution for my problem, as I have different domains.
Update
I found the solution for paths with the url
function but I still need a solution for assets.
Symfony Solutions
Solution 1 - Symfony
Symfony 2.7 has a new absolute_url which can be used to generate the absolute url. http://symfony.com/blog/new-in-symfony-2-7-the-new-asset-component#template-function-changes
It will work on those both cases or a path string:
<a href="{{ absolute_url(path('route_name', {'param' : value})) }}">A link</a>
and for assets:
<img src="{{ absolute_url(asset('bundle/myname/img/image.gif')) }}" alt="Title"/>
Or for any string path
<img src="{{ absolute_url('my/absolute/path') }}" alt="Title"/>
on those tree cases you will end up with an absolute URL like
http://www.example.com/my/absolute/path
Solution 2 - Symfony
For Symfony 2.7 and newer
See this answer here.
1st working option
{{ app.request.scheme ~'://' ~ app.request.httpHost ~ asset('bundles/acmedemo/images/search.png') }}
2nd working option - preferred
Just made a quick test with a clean new Symfony copy. There is also another option which combines scheme and httpHost:
{{ app.request.getSchemeAndHttpHost() ~ asset('bundles/acmedemo/images/search.png') }}
{# outputs #}
{# http://localhost/Symfony/web/bundles/acmedemo/css/demo.css #}
Solution 3 - Symfony
From Symfony2 documentation: Absolute URLs for assets were introduced in Symfony 2.5.
If you need absolute URLs for assets, you can set the third argument (or the absolute argument) to true:
Example:
<img src="{{ asset('images/logo.png', absolute=true) }}" alt="Symfony!" />
Solution 4 - Symfony
Daniel's answer seems to work fine for now, but please note that generating absolute urls using twig's asset
function is now deprecated:
> DEPRECATED - Generating absolute URLs with the Twig asset() function > was deprecated in 2.7 and will be removed in 3.0. Please use > absolute_url() instead.
Here's the official announcement: http://symfony.com/blog/new-in-symfony-2-7-the-new-asset-component#template-function-changes
You have to use the absolute_url
twig function:
{# Symfony 2.6 #}
{{ asset('logo.png', absolute = true) }}
{# Symfony 2.7 #}
{{ absolute_url(asset('logo.png')) }}
It is interesting to note that it also works with path
function:
{{ absolute_url(path('index')) }}
Solution 5 - Symfony
You probably want to use the assets_base_urls
configuration.
framework:
templating:
assets_base_urls:
http: [http://www.website.com]
ssl: [https://www.website.com]
http://symfony.com/doc/current/reference/configuration/framework.html#assets
Note that the configuration is different since Symfony 2.7:
framework:
# ...
assets:
base_urls:
- 'http://cdn.example.com/'
Solution 6 - Symfony
It's possible to have http://test_site.com and https://production_site.com. Then hardcoding the url is a bad idea. I would suggest this:
{{app.request.scheme ~ '://' ~ app.request.host ~ asset('bundle/myname/img/image.gif')}}
Solution 7 - Symfony
The following works for me:
<img src="{{ asset('bundle/myname/img/image.gif', null, true) }}" />
Solution 8 - Symfony
I've used the following advice from the docs https://symfony.com/doc/current/console/request_context.html to get absolute urls in emails:
# config/services.yaml
parameters:
router.request_context.host: 'example.org'
router.request_context.scheme: 'https'
Solution 9 - Symfony
Additional info to generate absolute URL using a command (to send an email for instance)
In a command, {{ absolute_url(path('index')) }}
is not working out of the box.
You will need to add the additional configuration shown in antongorodezkiy's answer.
But in case you don't want to change the configuration because you are not sure how it could impact the whole app, you can configure the router in the command.
Here is the doc :
https://symfony.com/doc/3.4/console/request_context.html
Here is the code :
use Symfony\Component\Routing\RouterInterface;
// ...
class DemoCommand extends Command
{
private $router;
public function __construct(RouterInterface $router)
{
parent::__construct();
$this->router = $router;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$context = $this->router->getContext();
$context->setHost('example.com');
$context->setScheme('https');
$context->setBaseUrl('my/path');
$url = $this->router->generate('route-name', ['param-name' => 'param-value']);
// ...
}
}
To generate the URL in the Twig template
<a href="{{ absolute_url(path(...)) }}"></a>
You can fetch the HOST and SCHEME from your env file
$context = $this->router->getContext();
$context->setHost($_ENV['NL_HOST']);
$context->setScheme($_ENV['NL_SCHEME']);
Just define the variable in .env and .env.local files
NL_HOST=mydomain.com
NL_SCHEME=https