Symfony 2 link to current page
php, routes, symfony, twig
Solution
I end up rolling my own function for this. I though at first it was included somewhere in `FrameworkBundle` but did not find anything about it. Here the steps I took.
At first, I created a Twig extension function that would output the same route as the one the user is visiting currently (parameters and query string included). I left this step to you. You can look at this link from a good tutorial on Symfony2 for the description of how to create a Twig extension if you don't know how already. I could help you with it if you need it.
Next step is to create the function itself that will switch the locale of the current route. This function will need the `Request` and `Router` objects as dependencies. In my personal case, I put this function in a dedicated service named `RoutingHelper` service. This service is then used by my Twig extension function. Here the service definition I added to the dependency container:
acme.helper.routing:
class: Application\AcmeBundle\Helper\RoutingHelper
scope: "request"
arguments:
request: "@request"
router: "@router"
And the constructor of my service:
protected $request;
protected $router;
public function __construct($request, $router)
{
$this->request = $request;
$this->router = $router;
}
The $locale parameter is new locale would like to switch to. Here the function:
public function localizeCurrentRoute($locale)
{
$attributes = $this->request->attributes->all();
$query = $this->request->query->all();
$route = $attributes['_route'];
# This will add query parameters to attributes and filter out attributes starting with _
$attributes = array_merge($query, $this->filterPrivateKeys($attributes));
$attributes['_locale'] = $locale;
return $this->router->generate($route, $attributes);
}
Essentially, it does what others have put so far but it also handles parameters and query string. The method `filterPrivateKeys` will remove private attribute from the route attributes. Those attributes are the one starting with an underscore and should not be passed back to the route generator. Here its defintion:
private function filterPrivateKeys($attributes)
{
$filteredAttributes = array();
foreach ($attributes as $key => $value) {
if (!empty($key) && $key[0] != '_') {
$filteredAttributes[$key] = $value;
}
}
return $filteredAttributes;
}
In the end, I'm able to this in my Twig view to create links to switch locales:
{% block language_bar %}
<a href="{{ localize_route('en') }}"> English </a>
<a href="{{ localize_route('fr') }}"> Français </a>
{% endblock %}
Edit:
Here my twig extension service definition:
acme.twig.extension:
class: Application\AcmeBundle\Twig\Extension\AcmeExtension
arguments:
container: "@service_container"
tags:
- { name: twig.extension }
And in the twig extension function I have this call: `$routingHelper = $this->container->get('acme.helper.routing');`
This should solve the scope widening exception happening because the twig extension is not in the request scope.
Update:
It is now possible with Symfony 2.1 to have a locale switcher in an easier way than before. Indeed, the 2.1 version of Symfony introduced a new parameter for routes that make it more easy to do a locale switcher. Here the code, all in twig
{% set route_params = app.request.attributes.get('_route_params') %}
{# merge the query string params if you want to keep them when switching the locale #}
{% set route_params = route_params|merge(app.request.query.all) %}
{# merge the additional params you want to change #}
{% set route_params = route_params|merge({'_locale': 'fr'}) %}
{{ path(app.request.attributes.get('_route'), route_params) }}
It is still a few lines of twig code, but could be included in a Twig block for easier reuse. Credits to stof, from the Symfony community, for the code above.
Hope this is what you are looking for.
Regards, Matt
Problem
How can i create a link to the current in my template? I want to create a language switcher which should link to the current page in varios languages, so all parameters should be the same exept for the locale.