Symfony2 form methods diffrent in Prod and Dev version - php

I have problem with my project.
My problem exist when I try to delete some data from entity. My controller was generated with Sesio generator. Here is my code:
/**
* Deletes
* #Route("/{id}/delete", name="delete")
* #Method({"DELETE"})
*/
public function deleteAction(Request $request, Task $task) {
$form = $this->createDeleteForm($task);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->remove($task);
$em->flush();
$this->get('session')->getFlashBag()->add('notice_success', 'Success');
} else {
$this->get('session')->getFlashBag()->add('notice_error', 'NO DELETE');
}
return $this->redirectToRoute('task');
}
/**
* Creates a form to delete.
*/
private function createDeleteForm(Task $task) {
return $this->createFormBuilder()
->setAction($this->generateUrl('delete', array('id' => $task->getId())))
->add('submit', \Symfony\Component\Form\Extension\Core\Type\SubmitType::class, array('label' => 'Delete'))
->getForm()
;
}
I have to tell you that this code work nice on DEV (app_dev.php) but It isn't working in PROD version.
I try to solve that problem and I have tried to change form method to POST and it work property od PROD and DEV. It look like DELETE method doesnt work in PROD version.
Someone have similar problem?

If you're using the AppCache, the kernel will ignore the _method parameter added for DELETE method.
To solve the problem in your web/app.php call Request::enableHttpMethodParameterOverride(); before creating the Request object:
...
$kernel = new AppCache($kernel);
Request::enableHttpMethodParameterOverride();// <-- add this line
$request = Request::createFromGlobals();
...
See http://symfony.com/doc/current/form/action_method.html and http://symfony.com/doc/current/reference/configuration/framework.html#configuration-framework-http-method-override

Related

Symfony forms & handling Doctrine constraint violations gracefully

I have built a form using symfony's form builder to create new entries with the doctrine entity manager, but upon creating new entries, I occasionally run into a Integrity constraint violation: 1062 Duplicate entry'. I would like to properly handle this exception using the DRY principles, what is the best way to do this gracefully?
Preferably I would have a warning show even before submitting but after submission would be acceptable also.
FlightController.php
/**
* #Route(path="/new", name="flight_new", methods={"GET", "POST"})
*/
public function new(Request $request)
{
//Create New Flight
$flight = new Flight($this->getDoctrine()->getManager());
$form = $this->createForm(FlightType::class, $flight);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$flight = $form->getData();
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($flight);
$entityManager->flush();
return $this->redirectToRoute("flight_list");
}
return $this->render('flight/new.html.twig', array('form' => $form->createView()));
}
Flight.php The constraint is a compound key:
/**
* #ORM\Entity(repositoryClass="App\Repository\FlightRepository")
* #ORM\Table(name="flight",
* uniqueConstraints={#ORM\UniqueConstraint(name="flight",columns={"ap_from","ap_to"})}
* )
*/
class Flight
{
Thanks in advance

Can't guess how to get a Doctrine instance

In a symfony projects, I'm trying to persist a line of an association table (profil_role) composed of two objects (profil and role).
First, I developed The create action in the ProfilRoleController of the second project this way:
/** #var Roles $role */
$em = $this->getDoctrine()->getManager('main_project');
$role = $em->getRepository("MyBundle\Entity\Roles")->find($roleId);
$profil = $em->getRepository("MyBundle\Entity\Profil")->find($profilId);
$profilRole = new ProfilRoles();
$profilRole->setRoleId($role->getId());
$profilRole->setProfilId($profil->getId());
$em->persist($profilRole);
$em->flush();
This part of code, call then the post entity action present in the main project:
/**
* #Rest\View(statusCode=Response::HTTP_CREATED)
* #Rest\Post("/profil_roles")
*/
public function postEntityAction(ProfilRoles $profilRole)
{
$em = $this->getDoctrine()->getManager();
$em->persist($profilRole);
$em->flush();
return $profilRole;
}
When I try to execute my code i'm getting this king of error:
Execution failed for request: POST /api/profil_roles? HTTP/1.1 {"profil":{"id":"12"},"role":{"id":"3"}}: HTTPCode 500, body {"code":500,"message":"Unable to guess how to get a Doctrine instance from the request information."}
I've tried to use the #ParamConverter annotation, but I don't how to use it my case.
try this:
public function postEntityAction() {
$postData = $request->request->all();
$profileRole = $postData['profile_role']
Instead of this:
public function postEntityAction(ProfilRoles $profilRole)
#AlessandroMinoccheri I've tried to be inspired by your reply to do this and i'ts workin, i don't know if it's the correct way.
/**
* #param ProfilRoles $profilRole
* #param Request $request
* #return ProfilRoles
* #Rest\View(statusCode=Response::HTTP_CREATED)
* #Rest\Post("/profil_roles")
*/
public function postEntityAction(Request $request)
{
$profilRole = new ProfilRoles();
$em = $this->getDoctrine()->getManager();
$requete = $request->request->all();
$profilRole->setProfilId($requete['profil']['id']);
$profilRole->setRoleId($requete['role']['id']);
$em->persist($profilRole);
$em->flush();
return $profilRole;
}

Can't upload file via Symfony 2.8 form upload

I've been trying to setup file upload via default symfony form and
Symfony\Component\HttpFoundation\File\UploadedFile.
I have really trivial form, with one input, button for file upload and submit button. Here is my conroller:
class DefaultController extends Controller
{
public function uploadAction(Request $request)
{
$document = new Elements();
$form = $this->createFormBuilder($document)
->add('name')
->add('file')
->add('save', SubmitType::class, array('label' => 'Create Task'))
->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$document->upload();
$em->persist($document);
$em->flush();
return $this->redirectToRoute('felice_admin_upload');
}
return $this->render('FeliceAdminBundle:Default:upload.html.twig', array(
'form' => $form->createView(),
));
}
}
And I have also created an entity, to persist data to database. I'm using doctrine. Everything that I did, was by manual:
http://symfony.com/doc/current/cookbook/doctrine/file_uploads.html
But the only exception was that I used yml, not annotations. After all, I have an error, when trying to upload file:
FileNotFoundException in File.php line 37:
The file "/tmp/phpFMtBcf" does not exist
What I am doing wrong?
Ok, I'm still haven't found an answer for my question. I've tried to search on different forums, in on French :) So my solutions in next. I gather file data manually, before actually handling a request, then I handle a request and next thing what I do, is I copy my file instead of moving. That is not getting my described error. So it should be quite refactored for beauty and convenience, but it works well. Thank you for attention.
class DefaultController extends Controller
{
/**
* #Route("/product/new", name="app_product_new")
*/
public function newAction(Request $request)
{
$product = new Product();
$form = $this->createFormBuilder(null, array('csrf_protection' => false))
->add('pic', FileType::class, array('label' => 'Picture'))
->add('Send', 'submit')
->getForm();
$pic = $request->files->get("form")["pic"];
$form->handleRequest($request);
if ($form->isValid()) {
// $file stores the uploaded PDF file
/** #var \Symfony\Component\HttpFoundation\File\UploadedFile $file */
$file = $pic;
// Generate a unique name for the file before saving it
$fileName = md5(uniqid()) . '.' . $pic->guessExtension();
// Move the file to the directory where brochures are stored
$brochuresDir = $this->container->getParameter('kernel.root_dir') . '/../web/uploads';
copy($pic->getPathname(), $brochuresDir . "/" . $fileName);
// Update the 'brochure' property to store the PDF file name
// instead of its contents
$product->setPic($fileName);
// ... persist the $product variable or any other work
return $this->redirect($this->generateUrl('app_product_new'));
}
return $this->render('FeliceAdminBundle:Default:index.html.twig', array(
'form' => $form->createView(),
));
}
}

Render controller in TWIG and show form errors

I have indexAction and contactAction
contactAction is a simple form with no mapped fields (FormType) like below:
/**
* #Route("/contact", name="contact")
* #Template()
* #param Request $request
* #return array
*/
public function contactAction(Request $request)
{
$form = $this->createForm(new ContactType());
$form->handleRequest($request);
if ($form->isValid()) {
$firstName = $form->get('first_name')->getData();
$lastName = $form->get('last_name')->getData();
$email = $form->get('email')->getData();
$message = $form->get('message')->getData();
}
return array(
'form' => $form->createView()
);
}
and i render this form in my indexAction with this TWIG command:
{{ render(controller('RusselBundle:Default:contact')) }}
Everything is okey, if page is not reloaded, HTML5 validators works fine, but if form have some errors like: firstName length, error's not show at all, how can i do, so that errors showed up in the form indexAction? Any help would be appreciated. I'm just curious it's possible, and if - how ? Sorry for my english....
Rather than using the request passed into the action you should get the master request from the request stack. As #DebreczeniAndrás says, when you use the render(controller()) you are using a newly created sub-request rather than the request that was actually passed to the page on load (the master request).
public function contactAction(Request $request)
{
$request = $this->get('request_stack')->getMasterRequest();
$form = $this->createForm(new ContactType());
//...
}
On symfony3 use render function like this
{{ render(controller('RusselBundle:Default:contact', {'request':app.request})) }}
If you use the render function in your twig, then that creates a subrequest, thus your original posted (i.e. in your main request) values get lost.
You can pass your main request to your form render action as follows:
{{ render(controller('RusselBundle:Default:contact'), 'request' : app.request ) }}
This will pass all the main request parameters appropriately to your subrequest.

Creating Contact Form using Symfony

I am trying to create a form using Symfony 2.5 using this tutorial, but this tutorial is using old version of Symfony. I can get the form to display and created the entity as well however I am now working on submitting the form. Following is the code from tutorial and this code is inside default controller contactAction
public function contactAction()
{
$enquiry = new Enquiry();
$form = $this->createForm(new EnquiryType(), $enquiry);
$request = $this->getRequest();
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
if ($form->isValid()) {
// Perform some action, such as sending an email
// Redirect - This is important to prevent users re-posting
// the form if they refresh the page
return $this->redirect($this->generateUrl('BloggerBlogBundle_contact'));
}
}
return $this->render('BloggerBlogBundle:Page:contact.html.twig', array(
'form' => $form->createView()
));
}
My main concerns is in the following section of above code
$request = $this->getRequest();
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
As you will notice it is using getRequest() which has been depricated and then my IDE is telling me buildRequest method cannot be found.
I will really appreciate if someone call push me towards the right path of converting the contactAction for symfony verion 2.5, I will really appreciate it.
Declare the action like this:
public function contactAction(Request $request)
{
...
}
And import:
use Symfony\Component\HttpFoundation\Request;
And you will have the request inside your action, so you can remove this line:
$request = $this->getRequest();
Hi there are a few deprecated calls also I would really recommend going to the cookbook in Symfony. But anyway this below will help.
namespace myproject/mybundle/controller;
use Symfony\Component\HttpFoundation\Request;
Class Act //that is me ;) {
/**
* #Route("/contact", name="_lalalalala")
* #Template()
*/
public function contactAction(Request $request){
$enquiry = new Enquiry();
$form = $this->createForm(new EnquiryType(), $enquiry);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($enquiry);
$em->flush();
return $this->redirect($this->generateUrl('BloggerBlogBundle_contact'));
}
return ['form' => $form->createView()];
}
}
You can shorten this code even further by using symfony services container to inject your form. I would recommend reading this it is pretty awesome. As you can re use forms anywhere :)
You can change the getMethod to isMethod like
if ($request->isMethod('POST'))
And then your can submit the request data to the form using submit like
$form->submit($request->request->get($form->getName()));
Alternatively you can use the handleRequest method that will handle the above 2 method in one go and then you can move on with the rest of your action like
$form->handleRequest($request);
if ($form->isValid())
.. etc
To retrieve the request object, you have two possibilities. Either let Symfony pass the request as an argument to your controller action ...
public function contactAction(Request $request)
{
// ...
}
... or get the request object from the container.
$request = $this->get('request');
For the binding of the request to the form, the manual states the following:
Passing the Request directly to submit() still works, but is deprecated and will be removed in Symfony 3.0. You should use the method handleRequest() instead.
This way, the request binding part would look similar to this:
if ($request->isMethod('POST')) {
$form->handleRequest($request);
if ($form->isValid()) {
// do something
}
}

Categories