I am creating a Symfony 4 web app that supports multiple languages. The routing is done, so I can have /en/suchpage or /de/suchpage. I am now looking for a way to link to "suchpage" using the right locale.
Routing looks as follows:
suchpage:
path: /{_locale}/suchpage/
controller: App\Controller\SimplePageController::such
requirements:
maw: '%app.locales%'
defaults:
_locale: '%locale%'
I am using Twig, and it is from Twig templates that I need to be able to link to the right version of a page. This "works":
{{ path('suchpage', {'_locale': app.request.locale}) }}
It has two issues though:
I do not want to be repeating this all over the place. Something like {{ page('suchpage') }} would be much better. Does a function like this exist? Can path() be made to behave like this?
This fails if the locale was not specified in the request, as can happen, since it is not required on all pages (since some have a default).
There is a maintened bundle, JMSI18nRoutingBundle, to achieve what you need.
composer require jms/i18n-routing-bundle
Some usefull links about this bundle :
Packagist : https://packagist.org/packages/jms/i18n-routing-bundle
GitHub : https://github.com/schmittjoh/JMSI18nRoutingBundle
Related
Hi I'm coming for a very simple question (I think) but i didn't found the answer or a similar case.
I'm using symfony 3 and trying to build a second menu for my administration pannel.
However, I have a problem about how I have to declare the relative url in my "href", For my main menu i used to do like this
{{ url ( 'admin' ) }}
and it worked. The fact is that now I have subfolders and many levels in my url.
The url i try to reach is myapp/admin/gameadmin, this url work when I'm going on it but when i try to put it in 'href' I have an error message which says that the route is not working.
i declared it like that ->
{{ url(admin/gameadmin) }}
I tried with different character -> admin:gameadmin, admin\gameadmin ... etc and with path instead of url i don't know if it's not the good way to declare it or if I have a problem with my controllers.
In my bundle it's organised like that :
->Controllers(folder)
->admin(folder) (You can also find my main controllers on this level)
->admingamecontroller (Where the page I try to reach is routed)
I hope i gave you all the informations, thank you for your help and sorry for my english !
The url parameter is not the the url per se (ie: admin/gameadmin), this is the route name, defined in your routing.yaml file, or in your controller annotation.
If your action is something like this:
/**
* #Route("/admin/gameadmin", name="gameadmin")
*/
public function gameAdminAction()
{
...
}
Then, to generate the route, you have to do this:
{{ url('gameadmin') }}
By doing this, all the links on your website will be up to date if you change the gameadmin url, as long as you don't change the route name.
I suggest you to read this documentation on the Symfony website: https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/routing.html
Edit: As pointed by user254319, if you're not using annotations, you'll have to edit your routing.yaml config file.
gameadmin:
path: /admin/gameadmin
controller: App\Controller\Admin\AdminGameController::gameadminAction
The route name is the yaml key: gameadmin.
Related Symfony documentation: https://symfony.com/doc/current/routing.html
I'm trying to call a controller from a twig extention.
I do not want to call the controller as a service since I'd lose all the fancy shortcuts.
Want I want to achieve is to call the controller like twig do it when you do :
{{ render(controller(
'AppBundle:Article:recentArticles',
{ 'max': 3 }
)) }}
I looked at the sourcecode of the "render" and tried to find the "controller" twig's functions, but I did not managed to understand how to do.
From now I achieved an unsatisfying but functionnal code :
In my twig extention :
return $environment->render('FooBundle:TwigExtension/CmsExtension:cmsRenderHook.html.twig', [
'hook' => $hook,
]);
In the CmsExtension:cmsRenderHook.html.twig template :
{{ render(controller(hook.stringControllerAction, hook.arrayParameters)) }}
I think (maybe wrongly) that it would be faster to call it without the template step.
EDIT : I finally successed to code this :
$environment->getExtension('Symfony\Bridge\Twig\Extension\HttpKernelExtension')->renderFragment(
$environment->getExtension('Symfony\Bridge\Twig\Extension\HttpKernelExtension')->controller(
$hook['action'],
$hook['jsonParameters']
)
);
(I did a grep in twig's cache and reproduced it compiled version).
my only concern is about referring to Symfony\Bridge\Twig\Extension\HttpKernelExtension, i'd rather let twig handle this choice, but I can't find out how.
I have two questions:
- do you think that Symfony\Bridge\Twig\Extension\HttpKernelExtension is stable enought to refere explicitly to it?
- if not how would you do to let twig handle it?
You could also get the Twig_SimpleFunction from the Twig_Environment:
$renderFunction = $environment->getFunction('render'); // get the env via initRuntime(..) in your extension
$callable = $renderFunction->getCallable();
However, I would not recommend relying on Twig internals. You should probably extract the functionality into a service.
I am porting my website which is in Kohana to Symfony 2 gradually. Right now I am writing backend command in Symfony2, e.g. cron to send email notifications.
How can I access base url in twig. Can I do some configuration so that accessing urls in twig from console and from http request to be same ?
I have already reffered to this,
http://symfony.com/doc/current/cookbook/console/sending_emails.html
http://symfony.com/doc/current/cookbook/templating/global_variables.html
here, it is given how to configure it, but it is not mentioned how to access it, I assume I have to use {{ router.request_context.host }}.
But my question is, isn't there any way to be consistent between console and HTTP ?
e.g. {{ url }} ?
Add following setting in parameters.yml,
router.request_context.scheme: http
router.request_context.host: domain.com
base_url: '%router.request_context.scheme%://%router.request_context.host%/'
and inside console command controller you can access like,
$host = $this->getContainer()->get('router')->getContext()->getHost();
$scheme = $this->getContainer()->get('router')->getContext()->getScheme();
$baseURL = $this->getContainer()->getParameter('base_url');
First, you must set the url (you're calling it base_url) in a route by adding the following lines to /app/config/routing.yml:
base_url:
pattern: /
After that, you must set the router.request_context parameters as mentioned in the Symfony cookbook.
Now that everything's setup, you can simply use the same url functions in Twig as you would do in your webpages:
{{ url('base_url') }}
This worked for me.
In config.yml:
twig:
globals:
base_url: "http://www.example.com/"
In twig template:
{{ base_url }}
I heve an embedded controller in my base template. It's a search bar.
For the search bar controller, I have a route "myProject/search".
What I would like is that this route will be taken only when the template where I am embedding the controller (base.html.twig) will call it, and not when i manually put in the browser: "myproject/search".
Any idea on how to do that.
I think, since some time you can't do it:
http://symfony.com/doc/current/book/templating.html#embedding-controllers
quote from the docs:
Even though this controller will only be used internally, you'll need
to create a route that points to the controller
(...)
Since Symfony 2.0.20/2.1.5, the Twig render tag now takes an absolute
url instead of a controller logical path. This fixes an important
security issue (CVE-2012-6431) reported on the official blog. If your
application uses an older version of Symfony or still uses the
previous render tag syntax, you should upgrade as soon as possible.
Anyway, I guess, you can try do it yourself by passing some "secret" argument to search action when you call it from your template. Next in the action you check if the argument was passed to it, and if not you throw 404.
Another way to achieve your goal is use .htaccess file.
You can restrict your route to a certain method by _method option in your routing configuration:
your_rote:
pattern: /myProject/search
defaults: { _controller: YourBundle:YourController:YourAction }
requirements:
_method: POST
With Silex (the PHP micro framework), it's possible to give names to existing controllers, so that we can easily generate urls to them later. Example:
$app->get('/gallery', function () {...})
->bind('gallery');
// Later on, in a template
{{ path('gallery') }}
I think this is really useful and I can't live without it.
But is it possible to register a route to an external website ? Say I'd like to generate urls to a google search, kind of
{{ path('google', {'search':'symfony'}) }}
// Would render to http://google.com/search?q=symfony
I take any idea :) Thx for your help !
path() is a Twig Extension for routing. Routing is to route an incoming URL to a controller action.
You can, however, create your own twig extension if you want a helper to easily create those standard outgoing URLs.
Take a look at: http://symfony.com/doc/current/cookbook/templating/twig_extension.html
You could then create an extension that turns {{ google('search string') }} into a URL. Only the imagination is your boundary.