I created a HomeController to show my homepage
class HomeController extends AbstractController
{
#[Route('/{page?}', name: 'home')]
public function index(PostRepository $pr, EntityManagerInterface $em, $page, ): Response
{
…
}
}
So far so good. But this stops working when I create a second page because it will always be catched by the home route.
For example my security controller always get's redirected to home when called with path('app_login')
class SecurityController extends AbstractController
{
/**
* #Route("/login", name="app_login")
*/
public function login(AuthenticationUtils $authenticationUtils): Response
{
It seems like the home route is too greedy and catches almost everything.
I suggest you to create requirements for your route param. Without it your home route will match any request that start with / followed by a string.
#[Route('/{page?}', name: 'home', requirements={"page"="\d+"})]
public function index(PostRepository $pr, EntityManagerInterface $em, $page = 1): Response {
//…
}
I'm not very sure how to handle that ?, with a default value I think you don't need it anymore.
https://symfony.com/doc/current/routing.html#parameters-validation
Related
I have made a controller (not a crud) with this extension :
class ScanController extends AbstractDashboardController
In this controller, I have a process with more steps and for each step I have create a action :
/**
* #Route("/scan/step1", name="scan_step1")
*/
public function step1(Request $request, EntityManagerInterface $entityManager): Response
{
}
/**
* #Route("/scan/step2/{id_scan}", name="scan_step2")
*/
public function step2(int $id_scan, Request $request, EntityManagerInterface $entityManager): Response
{
}
In my dashboard menu config I have add a menu to the first step :
MenuItem::linktoRoute('Scan', 'fa fa-barcode', 'scan_step1'),
The url of the Step1 is :
https://xxx/admin?menuIndex=2&routeName=scan_step1&signature=WeCEAS5-LhXL1Zy50HTVPuFjUpDKc7K0vdBLUY-T45E&submenuIndex=1
And this is ok but now, when I have done in the step1, I want to redirect the customer to the Step2 and I have used the simple "redirectToRoute" function :
return $this->redirectToRoute('scan_step2', [
'id_scan'=>$scan->getId(),
]);
But when the page is open, I don't have any menu any more....I'm in the template but "outside" the easyadmin "world"
and the URL is now :
https://xxxx/scan/step2/14
I'm sure that I need to generate by redirect URL with a easyadmin function but I dont find the way to make this :-(
Is it the AdminUrlGenerator and something else and how ?
I have find the solution.
First I extend with EasyAdminController :
class ScanController extends EasyAdminController
{
}
and for the redirection :
$url = $this->adminUrlGenerator
->setRoute('scan_step2',[
'id_scan'=>$scan->getId(),
])
->generateUrl();
return $this->redirect($url);
And Everything is fine now.
Here is the context : I have a multi country website and i have an url which is the same between France and Belgium website but I want them to redirect to different actions.
Here is a simple sample of my controller :
/**
* #Route({
* "fr": "/over-ons",
* "be": "/about-us"
* }, name="about_us")
*/
public function about()
{
die("about");
}
/**
* #Route({
* "fr": "/about-us",
* "be": "/over-ons"
* }, name="about_us_2")
*/
public function about2()
{
die("about 2");
}
Then, i created a LocaleSubscriber (based on https://symfony.com/doc/current/session/locale_sticky_session.html) :
<?php
namespace App\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
class LocaleSubscriber implements EventSubscriberInterface
{
private $defaultLocale;
public function __construct($defaultLocale = 'en')
{
$this->defaultLocale = 'fr';
}
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
$request->setDefaultLocale($this->defaultLocale);
$request->setLocale($this->defaultLocale);
$request->attributes->set('_locale', $this->defaultLocale);
$routeParams = $request->attributes->get('_route_params');
$routeParams['_locale'] = $this->defaultLocale;
$request->attributes->set('_route_params', $routeParams);
}
public static function getSubscribedEvents()
{
return [
// must be registered before (i.e. with a higher priority than) the default Locale listener
KernelEvents::REQUEST => [['onKernelRequest', 20]],
];
}
}
Then i opened http://localhost/about-us and wanted to see the message "about 2" but i have "about".
So the road "about-us" with locale "fr" shoud be matched with about2 action but it matches with about action.
Do you kown if it is possible that the Router match a route with a specific locale please ?
Thanks for your help !
It won't work like that.
The router will match request to the first matching route. So at that point it has very little to do with locale.
A request comes in with the path of /about-us, and it is matched to the about action with the be locale, because that route is defined first.
If you want to use the same route names for multiple locales you will have to add the locale to the URL. Subdomain, prefix, etc, doesn't really matter.
For example:
fr/about-us
be/about-us
(Of course you don't need to do it one by one, define it as a prefix in YAML)
I'm facing a problem that I don't understand. I simply create a Controller with make:controller and everything works, but when I want to create a new method, my route annotation doesn't work (whereas the default one works normally). T
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
class DefaultController extends AbstractController
{
/**
* #Route("/default", name="default")
*/
public function index()
{
return $this->render('default/index.html.twig', [
'controller_name' => 'DefaultController',
]);
}
/**
* #Route("/", name="home")
*/
public function home() {
return $this->render('default/home.html.twig');
}
}
The / route redirects me to the default page of Symfony and any other name for the route returns the No route found error.
Also, PHPStorm tells me that Import' Symfony\Component\Routing\Annotation\Route is never used when you can see that they are there...
How to solve this ? Thanks !
Check your config/routing.yaml
I'm issuing a POST body of: controller=user&action=add
To the URL: my_site.com/
I want acoording to post run addAction from UserController
class UserController extends Controller
{
public function addAction()
{
//return $this->redirectToRoute('test');
return $this->render('BeerwerdClaberonBundle:Default:index.html.twig');
}
}
How can I do this?
You can specify a route and with that route you can specify a request method.
For example:
/**
* #Route("/contact")
* #Method("GET")
*/
For more info see the documentation on routing:
http://symfony.com/doc/current/book/routing.html#adding-http-method-requirements
I've defined a route in my app routing file:
RouteName:
pattern: /some/route
defaults: { _controller: MyAppBundle:Controller:action }
In a controller I can use:
$this->get('router')->generate('RouteName');
How would I simply access that from a fresh class I create, for example a view class that doesn't extend anything:
namespace My\AppBundle\View;
class ViewClass {
public function uri()
{
return getTheRoute('RouteName');
}
}
You need to inject "router" service into your ViewClass. Eg. in place where your define your ViewClass service:
viewclass.service:
class: Namespace\For\ViewClass
arguments:
router: "#router"
and then in your constructor:
public function __construct(\Symfony\Bundle\FrameworkBundle\Routing\Router $router)
{
$this->router = $router;
}
The clue is in how the $this->generateUrl() method works in Controllers. See:
/**
* Generates a URL from the given parameters.
*
* #param string $route The name of the route
* #param mixed $parameters An array of parameters
* #param Boolean $absolute Whether to generate an absolute URL
*
* #return string The generated URL
*/
public function generateUrl($route, $parameters = array(), $absolute = false)
{
return $this->container->get('router')->generate($route, $parameters, $absolute);
}
So you'll need to define your class as a service and inject the #router service. Either that or have your class implement ContainerAwareInterface, but the first method would definitely be better.
You should register your class as a service and insert the router as a dependency.
See the chapter on the service container in the excellent symfony2 docs.
If you're not familiar with the concepts of the service container and dependency injection, you might feel a bit overwhelmed. However, try your best to understand it because it is a essential part of the symfony2 architecture.
You could pass the entire container from your controller to your view class on instantiation. This is NOT BEST PRACTICE and not recommended.
class View
{
protected $container;
public function __construct(\Symfony\Component\DependencyInjection\Container $container)
{
$this->container = $container;
}
}
Then in your code you could use
$this->container->get('router')->generate($route, $parameters, $absolute);