I have a problem with the symfony routing.
For an multilanguage projekt I render a Twig template via a job queue for mailing. In this template is a link to a route that requires the "_locale" parameter with "de" or "en" for example. I use the function "{{ url('route', {'_locale': 'de'}) }}" to generate the url.
By rendering the template, I got the following error message:
[Twig_Error_Runtime]
An exception has been thrown during the rendering of a template ("Some mandatory parameters are missing ("_locale") to generate a URL for route "Route".") in "TemplatePath" at line 5.
Whats my mistake?
Thanks for help
When you are generating URL route, via CLI, the Symfony kernel is missing a HTTP Request, and a Routing->RequestContext.
Thats why, the URL generator cannot find _locale parameter.
To fix it, you must manually create a RequestContext, so, in your command:
$this->getContainer()->get('router')
->setContext(
(new RequestContext())
->setParameter('_locale', 'fr')
);
class BaseCommand extends ContainerAwareCommand
{
protected function getLocale()
{
return $this->getContainer()->get('translator')->getLocale();
}
protected function render($view, $data)
{
return $this->getContainer()->get('templating')->render($view, $data);
}
}
in command
class SomeCommand extends BaseCommand
{
...
$this->render($view, array_merge($data, ['_locale' => $this->getLocale()])
}
in view
{{url('any', {param: 'foo'}|merge(_locale is defined ? {'_locale': _locale } : {}))}}
It's necro time :)
I'm just guessing here, but there's a couple things you can try.
Can you set the locale in your command?
Set the locale for the translator bundle:
$this->getContainer()->get('translator')->setLocale('de');
Set the locale for this session:
$this->getContainer()->get('session')->setLocale('de);
Internationalized routing for Symfony 4.1 and higher
If this applies to you, try this:
url('route.de', {'_locale': 'de'}) }}"
Does your route have 'de' and 'en' set as a requirement?
/**
* Matches /route
* #Route(
* "/route/{_locale}",
* requirements={
* '_locale': 'en|de'
* },
* name="route"
* )
*/
It's an old question but this might help someone out.
Related
I'am currenty face to this error when i try to get my article page : Cannot autowire argument $article of "App\Controller\HomeController::show()": it references class "App\Entity\Article" but no such service exists.
I just created a very new small symfony 5 application :
The code in my controller is :
/**
* #Route("/show/{id}", name="show")
*/
public function show(Article $article): Response
{
if(!$article) {
return $this->redirectToRoute('home');
}
return $this->render('show/index.html.twig', [
'article' => $article,
]);
}
I'am following a tutorial on Udemy and i guess that i did the same thing than the former. Maybe version difference ?
Thanks in advance for your helps.
Thierry
The error you have is saying that it cannot find the auto-wire path to your entity. Using the Symfony installer will automatically configure parts like this for you.
The main part which auto-wires the Entity to the Dependency Injection layer is through Doctrine configuration and the Symfony ParamConverter found as part of the SensioFrameworkExtraBundle.
The ParamConverter has a lot of options to be able to convert parameters inside of the #Route into an Entity. Using your example above we see that Symfony will internally call ArticleRepository->findOneById($id) and return the result to your controller.
EDIT: Removed all mentions of Doctrine configurations. The errors that are displayed when Doctrine is not auto-wiring are different.
Same problem here (with attributs instead of annotations) on Symfony 5
I have even tried to explicite ParamConverter and Entity:
#[Route('/article/{id}/editer', name: 'edit_article', requirements: ["id" => "\d+"], methods: ['GET','POST'])]
#[ParamConverter('id', options: ['mapping' => ['id' => 'id']])]
#[Entity('article', expr: 'repository.findOneBySlug(id)')]
public function editArticle(Article $article, Request $request,
CategoryRepository $categoryRepository, EntityManagerInterface $manager): Response
{
dump($article); die;
}
but i have got the error message:
Cannot autowire argument $id of "App\Controller\DefaultController::editArticle()":
it references class "App\Entity\Article" but no such service exists.
Although there is:
use App\Entity\Article;
And the solution like #nico-haase said is to install this bundle
composer require sensio/framework-extra-bundle
I am following the openclassrooms tutorial on symfony. I am now currently at the chapter "Les controleurs avec Symfony".
I try to open http://localhost/Symfony/web/app_dev.php and get this error
NotFoundHttpException
I suspect the error to come from AdvertController.php.
But I compared it with the given code at the tutorial. And it is exactly the same. I tried then to delete the cache but it does not function. I will open another question for that.
Here is the AdvertController.php code:
<?php
//src/Neo/PlatformBundle/Controller/AdvertController.php
namespace Neo\PlatformBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
//use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
class AdvertController extends Controller
{
public function indexAction()
{
$url= $this->get('router')->generate(
'neo_platform_view', //first argument : path name
array('id' => 5)
);
return new Response("The url of the announcement is:".$url);
}
public function viewAction($id)
{
return new Response("Desplay of the announcment with id:".$id);
}
public function viewSlugAction($slug, $year, $_format)
{
return new Response(
"We could desplay the announcment conrresponding the the slug
'".$slug."', created in ".$year." and with the format ".$_format."."
);
}
}
?>
If you would like me to post other parts of code, please let me know.
I have no idea, where to look at.
Thank you very much!
You can try to dump your routes with the command php bin/console debug:router or app/console for symfony <3.0 to see if there is a route your your desired path.
If you have the prefix /platform, your paths inside your controller are now /platform/path instead of /path.
You need a default route for your root path.
The message error is very explicit, there are not routes for "/". Try to verify your routing.yml
I have a 404 error page set up through an event listener triggered by Kernel exceptions:
public function onKernelException(GetResponseForExceptionEvent $event)
{
if ($event->isMasterRequest()) {
$exception = $event->getException();
if ($exception instanceof NotFoundHttpException) {
$response = new Response();
$event->setResponse(
$response->setContent($this->templating->render(
'LandingPageBundle:Error:error404.html.twig',
['welcome_url' => $this->router->generate("welcome")]
))
);
}
}
}
kernel.kernel_exception_listener:
class: S\Project\LandingPageBundle\EventListener\KernelExceptionListener
arguments: [ "#router", "#logger", "#translator", #templating ]
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException }
This works, but when I try to use the trans filter on the twig error404.html.twig template, it does nothing. My locale is being set in a cookie and read by an event listener to Kernel Requests, so I tried adding the following to onKernelException:
$request = $event->getRequest();
$locale = $request->cookies->get('_locale');
$request->setLocale($locale);
After that, including {{ app.request.locale }} in the template displayed the correct locale, however, the trans filter does not seem to be picking this up.
It seems like my problem may be related to Symfony 2.1 set locale and yet that question does not quite fit my exact problem, and I'm not sure what can be done to fix the problem. Ideally my kernel request listener could trigger before the onKernelException, so that it would properly set the locale beforehand, but currently it seems that the kernel request event is not triggered during a 404. I took a look at http://symfony.com/doc/current/components/http_kernel/introduction.html to better understand Symfony's request sequence, but I'm not really clear on the sequence that happens in a bad request, but it looks like in the case of an exception, it skips most of the request flow and goes straight to the response, and as I recall from http://symfony.com/doc/current/book/translation.html#handling-the-user-s-locale
"Setting the locale using $request->setLocale() in the controller is too late to affect the translator. Either set the locale via a listener (like above), the URL (see next) or call setLocale() directly on the translator service."
Is there a way to use the trans filter on a twig templated 404 page?
Try to inject the #translator and use its method setLocale.
['welcome_url' => $this->router->generate("welcome")]
And why did you create link in the listener? You should do it in the template using twig function called path.
I'm using just the framework without the CMS module for the first time. When I visit the app via a URL that is not handled by a controller/action, I just get a page with the text "No URL rule was matched". This results from Director::handleRequest() not matching any controllers to the url segments... Or "Action 'ABC' isn't available on class XYZController."
I'd like to direct any unmached requests to a controller equivalent of a nice 404 page. What is the correct or best way to do this?
The error templates are only included in the CMS. The framework just returns the HTTP response code with a message in plain text.
I've just started on my own framework-only project too and this is my solution:
[routes.yml]
---
Name: rootroutes
---
Director:
rules:
'': 'MyController'
'$URLSegment': 'MyController'
[MyController]
class MyController extends Controller {
private static $url_handlers = array(
'$URLSegment' => 'handleAction',
);
public function index() {
return $this->httpError(404, "Not Found");
}
/**
* Creates custom error pages. This will look for a template with the
* name ErrorPage_$code (ie ErrorPage_404) or fall back to "ErrorPage".
*
* #param $code int
* #param $message string
*
* #return SS_HTTPResponse
**/
public function httpError($code, $message = null) {
// Check for theme with related error code template.
if(SSViewer::hasTemplate("ErrorPage_" . $code)) {
$this->template = "ErrorPage_" . $code;
} else if(SSViewer::hasTemplate("ErrorPage")) {
$this->template = "ErrorPage";
}
if($this->template) {
$this->response->setBody($this->render(array(
"Code" => $code,
"Message" => $message,
)));
$message =& $this->response;
}
return parent::httpError($code, $message);
}
}
[ErrorPage.ss]
<h1>$Code</h1>
<p>$Message</p>
You can also create more specific error templates using ErrorPage_404.ss, ErrorPage_500.ss etc.
Without updating the routes as previously mentioned, there's a module that I've been recently working on which will allow regular expression redirection mappings, hooking into a page not found (404). This has been designed to function with or without CMS present :)
https://github.com/nglasl/silverstripe-misdirection
It basically makes use of a request filter to process the current request/response, appropriately directing you towards any mappings that may have been defined.
Is there any configuration in Symfony2 that allow use of case Insensitive routing?
For example, routes below should be treated as they are the same:
www.exmaple.com/all
www.exmaple.com/ALL
There is a pull request about this, but no reference how to make it happen.
As of Symfony2.4, you can now define condition to your route and use the expression language to do complexe check. See Router: Completely Customized Route Matching with Conditions documentation.
Another solution would be to override the route compiler class to change/extend the php compilation of your route matcher:
contact:
path: /{media}
defaults: { _controller: AcmeDemoBundle:Main:contact, media: organic }
requirements:
media: email|organic|ad
options:
compiler_class: MyVendor\Component\Routing\CaseInsensitiveRouteCompiler
See Symfony\Component\Routing\RouteCompiler class.
Or, as fabpot said in the pull request comment, your could override Request::getPathInfo[1] method to always return a lowercase string (use the setFactory[2] to override default request class).
*1 github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Request.php#L866
*2 github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Request.php#L402
I found a nifty way to do this in pure symfony (no apache mod_rewrite) without having to create a case-insensitive forwarding rule for every route.
This utilizes the twig ExceptionController. Because this occures after the routing has failed to match (or a 404 exception has been thrown for some other reason) it won't break any existing routing urls that use capitals (though that would still be a bad idea).
namespace Application\Symfony\TwigBundle\Controller;
use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Bundle\TwigBundle\Controller\ExceptionController as BaseExceptionController;
/**
* ExceptionController.
*/
class ExceptionController extends BaseExceptionController
{
/**
* Redirects 404s on urls with uppercase letters to the lowercase verion,
* then uses it's parent class to
* Convert an Exception to a Response.
*
* #param Request $request The request
* #param FlattenException $exception A FlattenException instance
* #param DebugLoggerInterface $logger A DebugLoggerInterface instance
*
* #return Response
*
* #throws \InvalidArgumentException When the exception template does not exist
*/
public function showAction(Request $request, FlattenException $exception, DebugLoggerInterface $logger = null)
{
if ( (string) $exception->getStatusCode() === '404' && preg_match('/[A-Z]/', $request->getPathInfo())) {
$lowercaseUrl = strtolower($request->getPathInfo());
if ($request->isMethod('POST')) {
return new RedirectResponse(
$lowercaseUrl,
'307'//307 status code preserves post information.
);
}
$queryString = $request->getQueryString();
return new RedirectResponse(
$lowercaseUrl.( strlen($queryString)>0 ? '?'.$queryString : '' ),
'301'//301 status code plays nice with search engines
);
}
return parent::showAction($request, $exception, $logger);
}
}
The only other trick is that you need to configure this controller as a service you can inject the correct arguments into the parent class's constructor:
in services.yml
services:
application.custom.exception_controller:
class: Application\Symfony\TwigBundle\Controller\ExceptionController
arguments: [ "#twig", "%kernel.debug%" ]
in config.yml:
twig:
exception_controller: application.custom.exception_controller:showAction
Of course, you can stick this controller and service definition anywhere
As far as I know, this isn't possible with Symfony 2. However, you should be able to accomplish it with Apache's mod_rewrite. See this blog post for details.
Make sure to read the comments, as there are some errors with the initial post.