How to set csrf option in symfony - php

I want to set CSRF error bubbling to false in symfony, on a form, using form builder.
I thought this would do it
$builder->get('_token')->setErrorBubbling(false);
but it gives me
The child with the name "_token" does not exist.
The csrf_field_name is set to '_token'. So, does the token get generated after my form building or something? Any ideas how I can do this?
many thanks
Dave

If you want to disable the CSRF token you have two options:
When creating the form on the controller pass an option:
$form = $this->createForm(new AcmeForm(), $acme, array(
'csrf_protection' => false
));
Or as default option on your form class:
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'csrf_protection' => false
}

Related

Symfony 5 $form->isSubmitted() Returning False for File Upload

I am attempting to upload a file via an API endpoint controller I have created:
/**
* #Route("/upload", methods="POST")
*/
public function upload(Request $request)
{
$form = $this->createForm(UserFileType::class);
$form->handleRequest($request);
if (!$form->isSubmitted()) {
dd($request->files->get('file'));
}
...
The dd($request->files->get('file')) is showing my file as expected so I am unclear why isSubmitted() is returning false when the method is receiving multipart/form-data POST request with data. I am submitting the POST request via Postman. Why is the form not submitted?
UserFileType:
class UserFileType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('file', FileType::class, [
'mapped' => false,
'required' => true,
'constraints' => [
new File([
'maxSize' => '2M',
'mimeTypes' => [
'application/pdf',
'application/x-pdf',
],
'maxSizeMessage' => 'The file size must not exceed {{ limit }} {{ suffix }}.',
'mimeTypesMessage' => 'The file type {{ type }} is not valid',
])
],
]);
}
For form classes derived from AbstractType, the form is named using fqcnToBlockPrefix when it's built through FormFactory.
You can confirm this by dumping $form->getName().
Now, $form->handleRequest method as implemented performs a number of checks through the request handler before submitting the form.
Checks the method matches that of the form
Checks the name of the form is present in the request if the form has a name
Checks that at least one of the form fields are filled if the form has no name
Your form is not submitting through the request handler handleRequest method because fields in the request are not properly mapped together with your form name.
You have to map the form name in your HTTP POST request in following way:
[ "user_file" => [ "file" => <uploaded file> ] ]
This may prove to not be straight forward in Postman.
Therefore I recommend to implement your form as a nameless form instead by overriding getBlockPrefix to return an empty string.
class UserFileType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
//...
}
public function getBlockPrefix()
{
return '';
}
}
Since this is the first SO thread that comes up for the keywords handlerequest issubmitted false, I thought I would share what worked for my team on an adjacent issue.
We were getting a false response when doing a PATCH request. We eventually realized that we were neglecting to pass Request::METHOD_PATCH in the method option when creatin the form. Putting in a ternary statement that set that value was enough to solve our problem.
I hope this helps someone.

Symfony manually validate entity with relation

I want to validate a User entity with custom constraint & validator. So far it's working when triggered by form workflow, but if I trigger it manually, I loose one relation I setup before calling validation :
UserController :
$user = new User();
$user->setRoles($roles);
$user->setSite($site);
...
$violations = $this->container->get('validator')->validate($user);
User entity with Site relation :
/**
* #var Site the site linked to the entity
* #ORM\ManyToOne(targetEntity="LCH\MultisiteBundle\Entity\Site", cascade={"all"})
* #ORM\JoinColumn(name="site_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $site;
Validator :
public function validate($user, Constraint $constraint)
{
$email = $user->getEmail();
// $site var is null while other "direct fields are filled
$site = $user->getSite();
$roles = $user->getRoles();
$username = $user->getUsername();
How can I manually validate this entity using preceeding set relation?
My problem found its origin in Symfony2 form validation structure. : as $form->handleRequest($request) indeed validates form, all hooked validators (groups, custom constrains and callbacks) are triggered.
My $site was null because validator was fired long before I set up my $user->site attribute...
// sumbit in this method trigger validation too early in my needs
$form->handleRequest($request);
$em = $this->getDoctrine()->getManager();
if ($form->isSubmitted() && $form->isValid() && !$isAjax) {
// custom processes to decide what to create
...
// Here is the user creation
$user->setRoles($roles);
$user->setSite($site);
...
// And the check
$violations = $this->container->get('validator')->validate($user);
}
The solution here lied in disabling validation groups in the main type. Doing so, $user is fully passed to validator.
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'validation_groups' => false,
));
}
The main drawback with this system is that I have to manually trigger validation for this very type in all interactions, but this type is complex enough to make sense here.

Symfony2: Create two controllers one to display a form and other to handle the submission

Hi I am a new to the Symfony2 MVC framework. What I have achieved so far is rendering a form in a twig template using the twig template. What I want to do next is create second (separate) controller to deal with form submission. Can you share with me how to achieve this.
I have read the symfony2 documentation however, it is not working.
Many thanks:)
You need to set an action on the form you are generating like so:
public function generateSearchBarAction()
{
$form = $this->createFormBuilder()
//This is where we are defining the target route
->setAction($this->generateUrl('route_to_catch_the_request'))
->setMethod('POST')
->add('keyword')
->getForm()
;
return $this->render('search_bar.html.twig', array(
'form' => $form->createView()
));
}
The controller that is provided at route_to_catch_the_request can then catch the request.
public function showSearchKeywordsAction(Request $request)
{
$form->handleRequest($request);
if ($form->isValid()) {
//do whatever...
}
}

Symfony2 - How to render a view from another controller

I have two controllers, homepage and Security.
In the homepage, I am displaying one view and in the security, I am doing some things, and one of them is the email address validation.
What I would like is that when the email validation code is not valid, display the homepage with a flash message. For that, I will have to render the indexAction of the HomepageController, from the Security controller, by giving him as parameter the flash message.
How can this be done? Can I render a route or an action from another controleller?
Thank you in advance.
I believe the checking should not be done in the Security controller. Right place in my opinion is a separate validator service or right in the entity which uses the email address.
But to your question, you can call another controller's action with $this->forward() method:
public function indexAction($name)
{
$response = $this->forward('AcmeHelloBundle:Hello:fancy', array(
'name' => $name,
'color' => 'green',
));
return $response;
}
The sample comes from symfony2 documentation on: http://symfony.com/doc/2.0/book/controller.html#forwarding
I have found the solution, simply use the forward function by specifying the controller and the action nanme:
return $this->forward('MerrinMainBundle:Homepage:Index', array('flash_message'=>$flash_message));
redirectToRoute : Just a recap with current symfony versions (as of 2016/11/25 with v2.3+)
public function genericAction(Request $request)
{
if ($this->evalSomething())
{
$request->getSession()->getFlashBag()
->add('warning', 'some.flash.message');
$response = $this->redirectToRoute('app_index', [
'flash_message' => $request->getSession()->getFlashBag(),
]);
} else {
//... other logic
}
return $response;
}

Remove validation group from parent form

I use FOSUserBundle with a custom registration form that extends the one provided by the bundle. I want to override the validation so it doesn't check for a username (I generate it). I have read that this can be achieved thru the usage of validation groups.
These are the relevant parts of my form:
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
...
$builder->remove('username');
...
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Ysu\Bundle\SiteBundle\Entity\User',
'validation_groups' => array('my-registration-group'),
'cascade_validation' => true
));
}
...
However the username is still validated with the validation files provided by the bundle. I found out that $options (array) contains an array validation_groupswhich in its turn contains the 'Registration' group, so that is why the field is still validated. However, I don't know how to remove it. If I unset it from $optionsbefore passing it to parent::buildFormit will still contain the Registration group.
Does anyone know how to solve this?
Turns out you can configure the validation groups for the FOSUserBundle's forms in config.yml:
fos_user:
....
registration:
form:
validation_groups: [default, registration_mod]
....

Categories