Mr. B.
Mr. B.

Reputation: 8697

Symfony: how to get a parameter from the route within a FormType?

I'm trying to access the parameter page from the current route within a FormType. It works in a Controller, but not in a FormType. I'd like to avoid passing the parameter like /?page=1 and prefer /page/1.

routing.yml

my_route:
    path: /data/page/{page}
    defaults:
        _controller: MyBundle:MyController:myAction

src/myBundle/Form/Type/MyFormType.php

class MyFormType extends AbstractType {
    // ...
    public function buildForm(FormBuilderInterface $builder, array $options) {
        $request = Request::createFromGlobals();
        $page    = $request->query->get('page');
        echo "page: $page"; // empty

        // ...
    }
}

I'd like to avoid to pass the parameter through the Controller to the FormType and prefer to access it directly within the FormType.

Any ideas?

Thanks in advance!

Edit: Regarding the selected answer; the page attribute is accessible via $request->attributes->get('page'), not via $request->query->get('page').

Upvotes: 4

Views: 4364

Answers (3)

Cmalfr
Cmalfr

Reputation: 61

It is not necessary to inject the request stack service in the construct of your formtype. You can access to the requestStack by using form event listener like that:

$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$form = $event->getForm();
$form->getConfig()->getRequestHandler();
// do what you need...
});

Upvotes: 1

yceruto
yceruto

Reputation: 9585

You need to inject the request stack service into form type to do that:

class MyFormType extends AbstractType 
{
    private $requestStack;

    public function __construct(RequestStack $requestStack)
    {
        $this->requestStack = $requestStack;
    } 

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $request = $this->requestStack->getCurrentRequest();

        //do something: for example hide/show fields from request parameters  
    }
}

Register the form type and their dependencies:

services:
    app.form.type.myform:
        class: AppBundle\Form\Type\MyFormType
        arguments: ['@request_stack']
        tags:
           - { name: form.type }

However, is recommended instead to create the new option to pass all variables that you need for your form type.

Upvotes: 5

Keen
Keen

Reputation: 98

I'm not sure the answer provided by Yonel is the best because you inject a dependency to your form. It has some drawbacks and the major one IMHO is that it will make the test difficult as the dependency on the page parameter is hidden.

A better solution will be to add it as form option to your form.

The request object is already available in your controller and you are probably creating your form this way :

$form = $this->createForm(WhateverFormType::class, $entity)

Using the createForm method, you can inject a third argument which are the options (i.e additional data) you want to pass to your form.

So in your controller :

$page = $request->query->get('page');
$form = $this->createForm(WhateverFormType::class, $entity, ['page' => $page]);

And in your form type, follow the example given in this answer for the same question : https://stackoverflow.com/a/10922788/2721918

Upvotes: 5

Related Questions