Symfony redirect to route passing url slug - symfony

I've searched this on SO previously, but it seems that the only answers given are when parameters are passed as a query string, which is not what I want.
I have a page in my Symfony 3 CRM with a route app_litter. There is a required URL slug called litter_id which needs to be passed to the route in order to determine which litter data to show, as follows:
/litter/1
My route definiton in the routing file is:
app_view_litter:
path: /litter/{id}
defaults: { _controller: AppBundle:Litter:view, id: null }
requirements:
id: \d+
There is a function which allows a user to add puppies to their litter, which is a form outside of this page - once the puppies are successfully saved, I want to redirect the user back to the litter in question, so I did this:
return $this->redirectToRoute('app_litter', array('litter_id' => $litter->getId()));
Where $litter is the object retrieved from Symfony. However, this redirects to:
/litter?litter_id=1
Which does not work, as it expects a slug. Is it possible to use redirectToRoute() (or any other method) to render the route with a slug instead of a query string?

Because your route definition is:
app_view_litter:
path: /litter/{id}
defaults: { _controller: AppBundle:Litter:view, id: null }
requirements:
id: \d+
When using the route generator you need to provide an associated array with keys corresponding to the name of your placeholders which is in your case id.
Therefore, it must be:
$this->redirectToRoute('app_litter', array('id' => $litter->getId()));
If you want to use a slug, and there something which not only composed of digits (\d+), you have to either define a new route or modify the existing.
app_view_litter_using_slug:
path: /litter/{slug}
defaults: { _controller: AppBundle:Litter:view, slug: null }
requirements:
id: .*
And you something like:
$this->redirectToRoute('app_litter_using_slug', array('slug' => $litter->getSlug()));

Could it be that you are using the wrong route? Try using app_view_litter instead of app_litter:
return $this->redirectToRoute('app_view_litter', array('id' => $litter->getId()));

Related

symfony routing, use value from Request as default

I've got the following route definition
my_route:
path: /actual-path/
defaults:
_controller: MyBundle:MyController:detail
id: application_id
requirements:
methods: GET
id: \d+
The controller requires a parameter called $id.
But I don't want to use the $id in the url, I want to use a value that is available in $request->attributes->get('application_id')
There is a listener that will inject two parameters (application_id and application) into the request object as attributes prior to the routing process, so this value is in there. (It would be easy to also inject it into the RequestContext).
Is there a way I can use attributes values from the Request or RequestContext object in my routing as defaults?
Now I could simply do $request->attributes->get('application_id') in my controller. But this controller will be used in several cases. In other cases the $id is to be passed through the url. I find it cleaner to set the id in the routing than build a if-else clause in the controller somewhere.
It appears not to be possible to do "mapping" between variables in the request object and the parameters you need to be required in your route/controller-action. I think this would be a good thing, as it would become quite complex otherwise.
I went with the solution to extend the controller and build in a small switch there.
Basically, if the route specifies id === null, it will do a fallback to application_id that is in the Request object. Otherwise it will use the value provided. I just need to set a requirement on id on the routes that must not use the fallback.
All without running an additional Listener which might be a bit "expensive" in processing time (for each request).
Example of routes:
my_route:
path: /actual-path/
defaults:
_controller: MyBundle:MyController:detail
id: null
requirements:
methods: GET
my_other_route:
path: /other-path/{id}
defaults:
_controller: MyBundle:MyController:detail
requirements:
methods: GET
id: \d+
And how to handle this in your controller:
// fallback to system id
if ($id === null) {
$id = $request->attributes->get('administration_id', null);
}
Because you extend the controller/action, you could also change the name of the parameter in the action (as long as the type does not change).
I did not do this, as I could quite easily put the switch between the provided id and the fallback from the listener in another method.

there is no default value + symfony2 + crud

sf 2.8.4 with sylius 0.17
i had generated a controller and routes with generate:doctrine:crud
i can list all datas, but on show and edit, always got this error:
Controller "St\AppBundle\Controller\TranslationDomainController::showAction()" requires that you provide a value for the "$translationdomain" argument (because there is no default value or because there is a non optional argument after this one).
here the show action
public function showAction(TranslationDomain $translationdomain)
{
$deleteForm = $this->createDeleteForm($translationdomain->getId(), 'administration_translations_domain_delete');
return $this->render('StAppBundle:TranslationDomain:show.html.twig', array(
'translationdomain' => $translationdomain,
'delete_form' => $deleteForm->createView(), ));
}
and the route
administration_translations_domain_show:
pattern: /{id}/show
defaults: { _controller: "StAppBundle:TranslationDomain:show", id : 1 }
requirements:
id : \d+
_method : get
You are using a param converter
http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html
You have to disable the auto-conversion of type-hinted method arguments feature by setting the auto_convert flag to false.
Look at:
# app/config/config.yml
sensio_framework_extra:
request:
converters: true
auto_convert: false
Change to:
sensio_framework_extra:
request:
converters: true
auto_convert: true
At the end you should always request for an object identifier. It's safe and semantic correct. You want to 'show/edit/update/delete' concrete entity.
If you really wants to have a default show for your set of entities create route like a '/show/default' and use this route with 'show/choose default' link.

Symfony2 homepage different for authenticated users

How can I define my Symfony2 routes to show a different homepage for authenticated users and non-authenticated users? For example, I want to do something like this in my routing.yml file:
homepage_authenticated:
path: /
defaults:
_controller: AcmeBundle:Home:homeAuthenticated
requirements:
user: is_authenticated_remembered # <--- this part here
homepage:
path: /
defaults:
_controller: AcmeBundle:Home:home
Now obviously this doesn't work because I just invented it, but I'm sure there must be a way to do this, but I can't find it. I have an idea Expressions may be the solution to this somehow, but I can't find any examples of actually using them, anywhere.
As Malcom suggested in the comment, it is better to handle redirects/page-rendering based on user's authentication status in the controller.
The security context saves the role related data and the authentication status. You can redirect your users to different pages by checking
$this->get('security.context')->isGranted('IS_AUTHENTICATED_FULLY') and $this->get('security.context')->isGranted('ROLE_NAME').
For example:
public function homeAction()
{
$em = $this->getDoctrine()->getEntityManager();
if ($this->get('security.context')->isGranted('IS_AUTHENTICATED_FULLY')) {
//Path handling for authenticated users
if ($this->get('security.context')->isGranted('ROLE_ADMIN')) {
return $this->redirect($this->generateUrl('admin_homepage'));
}
if ($this->get('security.context')->isGranted('ROLE_USER')) {
return $this->render('VenomCoreBundle:Default:home.html.twig', array(
'notifications' => $notifications,
'unApprovedCount' => $unApprovedCount,
'status' => $stats,
));
}
}
//non authenticated users are redirected here
return $this->render('VenomCoreBundle:Default:login.html.twig');
}

Symfony 2 redirect route

I have the following route that works via a get:
CanopyAbcBundle_crud_success:
pattern: /crud/success/
defaults: { _controller: CanopyAbcBundle:Crud:success }
requirements:
_method: GET
Where Canopy is the namespace, the bundle is AbcBundle, controller Crud, action is success.
The following fails:
return $this->redirect($this->generateUrl('crud_success'));
Unable to generate a URL for the named route "crud_success" as such route does not exist.
500 Internal Server Error - RouteNotFoundException
How can I redirect with generateUrl()?
Clear your cache using php app/console cache:clear
return $this->redirect($this->generateUrl('CanopyAbcBundle_crud_success'));
If parameters are required pass like this:
return $this->redirect($this->generateUrl('CanopyAbcBundle_crud_success', array('param1' => $param1)), 301);
The first line of your YAML is the route name that should be used with the router component. You're trying to generate a URL for the wrong route name, yours is CanopyAbcBundle_crud_success, not crud_success.
Also, generateUrl() method does what it says: it generates a URL from route name and parameters (it they are passed). To return a 403 redirect response, you could either use $this->redirect($this->generateUrl('CanopyAbcBundle_crud_success')) which is built into the Controller base class, or you could return an instance of Symfony\Component\HttpFoundation\RedirectResponse like this:
public function yourAction()
{
return new RedirectResponse($this->generateUrl('CanopyAbcBundle_crud_success'));
}

How do I use Period in Route in Symfony2?

I'm trying to have a route in symfony that matches the following url:
/filename/version/
where filename is an image, say "image.png" and version as say "foo".
MyImageBundle_resize:
pattern: /{filename}/{sizename}/
defaults: { _controller: MyImageBundle:ImageResize:resize }
and this matchs the pattern /myfile/XXL/, for example. But when I use myfile.jpg, as in /myfile.jpg/XXL/ Symfony seems to break on the period, and returns 404. I found this article which suggests that everything except the "/" will match (which doesn't make any sense if the period is breaking here).
Is there a way I can have the route match on the period?
You don't need to allow slash in URL. Just use simple route:
file_check:
pattern: /check/{filename}/{version}
defaults: { _controller: AcmeDemoBundle:File:check }
And in your controller use:
public function checkAction($filename, $version)
{
//some action
}

Resources