i want to edit my data with symfony form and i have a problem
probably with my controller. I have some like this :
public function detailAction($id,Request $request)
{
$order = $this->getDoctrine()->getRepository(OrderMain::class)->find($id);
if (!$order) {
throw $this->notFoundException();
}
$form = $this->createForm(OrderMainType::class, $order);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// do not enter here
$orderEdit = $form-getData();
$em = $this->getDoctrine()->getManager();
$em->persist($orderEdit);
$em->flush();
}
return $this->render('ModiModiAdminBundle:Order:detail.html.twig',array(
'form' => $form->createView(),
));
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
/.../
->add('edit', SubmitType::class, array(
'attr' =>array('class'=>'edit'),
));
}
All show corectly but when i click a button my page is reload ( dosen't save changes ). Thanks for help.
It is an issue with your controller method. Below should work for you.
public function detailAction($id,Request $request)
{
$order = $this->getDoctrine()->getRepository(OrderMain::class)->find($id);
if (!$order) {
throw $this->notFoundException();
}
$form = $this->createForm(OrderMainType::class, $order);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
//do not enter here
$em = $this->getDoctrine()->getManager();
$em->flush();
}
return $this->render('ModiModiAdminBundle:Order:detail.html.twig',array(
'form' => $form->createView(),
));
}
You can remove the line of $orderEdit = $form-getData();. When your form is submitted, the entity should be updated based on the submitted data. Since this is already a managed entity, you can also remove $em->persist($orderEdit);
public function edit(Request $request)
{
$id = $request->get('id');
$category = $this->getDoctrine()->getRepository(Category::class)->find($id);
if (!$category) {
throw $this->notFoundException();
}
$form = $this->createForm(CategoryType::class,$category);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()){
$em = $this->getDoctrine()->getManager();
$categoryData = $form->getData();
$em->persist($categoryData);
$em->flush();
}
return $this->render('admin/category/edit.html.twig',array(
'form' => $form->createView(),
));
}
you are missing => handle request from code
$form->handleRequest($request);
Related
everyone.
I am building symphony 5 project, but I have an issue.
The URL is not redirecting after I create or edit an element.
But in other functions, the redirectToRoute() function works.
Strange problem...
These are my controller code.
Please check it and let me know what I missed.
Thanks.
/**
* #Route("/list", name="animals")
*/
public function animals(): Response
{
if (!$this->getUser()) {
$this->redirectToRoute('app_login');
}
$animals = $this->getUser()->getAnimals();
return $this->render('animals/overview.html.twig', [
'animals' => $animals,
]);
}
And
/**
* #Route("/create", name="animal_create")
*/
public function create(Request $request, EntityManagerInterface $entityManager): Response
{
$animal = new Animal();
$customer = $this->em()->getRepository(Customer::class)->findOneBy(array('id' => $request->request->get('customer')));
$animal->setCustomer($customer);
$form = $this->createForm(AnimalType::class, $animal, [
'csrf_protection' => false,
]);
$form->handleRequest($request);
if (!$form->isSubmitted() || !$form->isValid()) {
return new Response('failed');
}
$customer->addAnimal($animal);
$entityManager->persist($animal);
$entityManager->flush();
return $this->redirectToRoute('animals');
}
/**
* #Route("/{id}/update", name="animal_update")
*/
public function update(Request $request, Animal $animal, EntityManagerInterface $entityManager): Response
{
$form = $this->createForm(AnimalType::class, $animal, [
'csrf_protection' => false,
]);
$form->handleRequest($request);
if (!$form->isSubmitted() || !$form->isValid()) {
return new Response('failed');
}
$entityManager->persist($animal);
$entityManager->flush();
return $this->redirectToRoute('animals');
}
You must redirect to the index route only if the form is submitted and validated, otherwise the form must be displayed.
The symfony documentation explains this perfectly:
public function create(Request $request, EntityManagerInterface $entityManager): Response
{
$animal = new Animal();
$customer = $this->em()->getRepository(Customer::class)->findOneBy(array('id' => $request->request->get('customer')));
$animal->setCustomer($customer);
$form = $this->createForm(AnimalType::class, $animal);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$animal = $form->getData();
$customer->addAnimal($animal);
$entityManager->persist($animal);
$entityManager->flush();
return $this->redirectToRoute('animals');
}
// Here it's the name of your twig template for animal creation
return $this->renderForm('animal/create.html.twig', [
'form' => $form,
]);
}
Do the same thing for the update action.
hello im trying to complete this tutorial from this link https://www.tutorialspoint.com/symfony/symfony_complete_working_example.htm
ive done until Step 15: Collect Book Information and Store It
when i try to input from the newAction form i got the error message
Warning: count(): Parameter must be an array or an object that
implements Countable
oh i forgot mention im using symfony 2.8.3
here is my code
<?php
// scr/AppBundle/Controller/BooksController.php
namespace AppBundle\Controller;
use AppBundle\Entity\Book;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
class BooksController extends Controller {
/**
* #Route("/books/author")
*/
public function authorAction()
{
return $this->render('books/author.html.twig');
}
/**
* #Route("/books/display", name = "app_book_display")
*/
public function displayAction()
{
$bk = $this->getDoctrine()
->getRepository('AppBundle:Book')
->findAll();
return $this->render('books/display.html.twig', array('data' => $bk));
}
/**
* #Route("/books/new", name = "app_book_new")
*/
public function newAction(Request $request)
{
$book = new Book();
$form = $this->createFormBuilder($book)
->add('name', TextType::class)
->add('author', TextType::class)
->add('price', TextType::class)
->add('save', SubmitType::class, array('label' => 'Submit'))
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$book = $form->getData();
$doct = $this->getDoctrine()->getManager();
// tells Doctrine you want to save the Product
$doct->persist($book);
// executes the queries (i.e. the INSERT query)
$doct->flush();
return $this->redirectToRoute('app_book_display');
} else {
return $this->render('books/new.html.twig', array('form' => $form->createView(),
));
}
}
/**
* #Route("/books/update/{id}", name = "app_book_update")
*/
public function updateAction($id, Request $request)
{
$doct = $this->getDoctrine()->getManager();
$bk = $doct->getRepository('AppBundle:Book')->find($id);
if (!$bk) {
throw $this->createNotFoundException(
'No book found for id '.$id
);
}
$form = $this->createFormBuilder($bk)
->add('name', TextType::class)
->add('author', TextType::class)
->add('price', TextType::class)
->add('save', SubmitType::class, array('label' => 'Submit'))
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$book = $form->getData();
$doct = $this->getDoctrine()->getManager();
// tells Doctrine you want to save the Product
$doct->persist($book);
// executes the queries (i.e. the INSERT query)
$doct->flush();
return $this->redirectToRoute('app_book_display');
} else {
return $this->render('books/new.html.twig', array(
'form' => $form->createView(),
));
}
}
/**
* #Route("/books/delete/{id}", name = "app_book_delete")
*/
public function deleteAction($id)
{
$doct = $this->getDoctrine()->getManager();
$bk = $doct->getRepository('AppBundle:Book')->find($id);
if (!$bk) {
throw $this->createNotFoundException('No Book found for id '.$id);
}
$doct->remove($bk);
$doct->flush();
return $this->redirectToRoute('app_book_display');
}
}
i expect the output will be the input from form newAction will store the data and redirect me to display and show it the data from previous input
okay i solved this issue just create project using Symfony 2.8.39 they has fixed this issue https://symfony.com/blog/symfony-2-8-39-released
I have a Business Entity and a BusinessObject Entity, and I would like to link the BusinessObject to the current Business when I create a new BusinessObject.
For example, if my route is business/{id}/object/new, I would like to have the object related with the Business (thanks to the id).
In my BusinessObject Controller, I managed to use #ParamConverter to get the Business id.
In my BusinessObject Form, I put an HiddenType to my business entry because I don't want it to appear, and set data to business_ID.
I struggle in configureOptions to get the business ID, I can't figure out how to get the business id from here.
BusinessObject Controller (route new):
/**
* #Route("/{post_id}/new", name="business_object_new", methods="GET|POST")
* #ParamConverter("business", options={"id" = "post_id"})
*/
public function new(Request $request,Business $business): Response
{
$businessObject = new BusinessObject();
$businessID = $business->getId();
$form = $this->createForm(BusinessObjectType::class, $businessObject,array(
'business_ID'=>$businessID,
));
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($businessObject);
$em->flush();
return $this->redirectToRoute('business_object_index');
}
return $this->render('business_object/new.html.twig', [
'business_object' => $businessObject,
'business'=>$business,
'form' => $form->createView(),
]);
}
BusinessObjectType:
class BusinessObjectType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('object',TextType::class)
->add('complement')
->add('status')
->add('durationExpected')
->add('durationAchieved')
->add('client')
->add('projectManager')
->add('business',HiddenType::class,array(
'data' => $options['business_ID']
))
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => BusinessObject::class,
'business_ID'=>Business::class
]);
}
}
With this code, I get an error Expected argument of type "App\Entity\Business or null", "string" given. I think this have something to do with the function configureOptions() in my Form
The approach can be:
public function new(Request $request,Business $business): Response
{
$businessObject = new BusinessObject();
$form = $this->createForm(BusinessObjectType::class, $businessObject);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// I suppose your setter is `setBusiness`, otherwise use more suitable one
$businessObject->setBusiness($business);
$em = $this->getDoctrine()->getManager();
$em->persist($businessObject);
$em->flush();
Form builder is:
builder
->add('object',TextType::class)
->add('complement')
->add('status')
->add('durationExpected')
->add('durationAchieved')
->add('client')
->add('projectManager'); // No business field
Another option is to embed BusinessType form into BusinessObjectType, you can read more about form embedding here.
Suppose I have two entities: a post and a comment. Each post can have many comments. Now, suppose I have a comment form. It is supposed to take user input and store it in the database.
Simple stuff. At least, it should be, but I can't get it to work.
How do I refer to the post (parent) when creating the comment (child)? I tried manually passing the post_id to the comment form as a hidden field, but received an error complaining about how the post ID is a string.
Expected argument of type "App\Entity\Post or null", "string" given.
Here is my code so far. Can someone nudge me into the right direction?
CommentType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$post_id = $options['post_id'];
$builder->add('content', TextareaType::class, [
'constraints' => [
new Assert\NotBlank(['message' => 'Your comment cannot be blank.']),
new Assert\Length([
'min' => 10,
'minMessage' => 'Your comment must be at least {{ limit }} characters long.',
]),
],
])->add('post', HiddenType::class, ['data' => $post_id]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Comment::class,
'post_id' => NULL,
]);
}
PostController.php (this is where the comment form appears)
// Generate the comment form.
$comment = new Comment();
$form = $this->createForm(CommentType::class, $comment, [
'action' => $this->generateUrl('new_comment'),
'post_id' => $post_id,
]);
CommentController.php
/**
* #param Request $request
* #Route("/comment/new", name="new_comment")
* #return
*/
public function new(Request $request, UserInterface $user)
{
// 1) Build the form
$comment = new Comment();
$form = $this->createForm(CommentType::class, $comment);
// 2) Handle the submit (will only happen on POST)
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid())
{
// 3) Save the comment!
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($comment);
$entityManager->flush();
}
return $this->redirectToRoute('homepage');
}
Thank you very much for your help!
You just need to pass the actual Post entity, not just the id. Try this:
CommentController.php
public function new(Request $request, UserInterface $user, Post $post)
{
// 1) Build the form
$comment = new Comment();
$comment->setPost($post); //where $post is instance of App\Entity\Post
$form = $this->createForm(CommentType::class, $comment);
// 2) Handle the submit (will only happen on POST)
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid())
{
// 3) Save the comment!
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($comment);
$entityManager->flush();
}
return $this->redirectToRoute('homepage');
}
CommentType
public function buildForm(FormBuilderInterface $builder, array $options)
{
//don't need to set the $post here
$builder->add('content', TextareaType::class, [
'constraints' => [
new Assert\NotBlank(['message' => 'Your comment cannot be blank.']),
new Assert\Length([
'min' => 10,
'minMessage' => 'Your comment must be at least {{ limit }} characters long.',
]),
],
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Comment::class
//don't need the default here either
]);
}
Comment Entity
class Comment
{
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Post")
*/
private $post;
//other vars
public function setPost(\App\Entity\Post $post): void
{
$this->post = $post;
}
public function getPost(): \App\Entity\Post
{
return $this->post;
}
//other functions
}
This code works for me:
CommentController.php
As suggested by flint above, you just need to pass the actual Post entity, not just the id. Then if you have this error "Unable to guess how to get a Doctrine instance from the request information for parameter "post" this is because you need to add the post slug in the path of the new_comment route. The ParamConverter is called implicitly and it need this slug {post} with the same name as the name you used for the post parameter in the function.
/**
* #param Request $request
* #return \Symfony\Component\HttpFoundation\RedirectResponse
* #Route("/comment/new/{post}", name="new_comment")
*/
public function new(Request $request, Post $post)
{
$comment = new Comment();
$comment->setPost($post); //where $post is instance of App\Entity\Post
$form = $this->createForm(CommentType::class, $comment);
// 2) Handle the submit (will only happen on POST)
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid())
{
// 3) Save the comment!
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($comment);
$entityManager->flush();
}
return $this->redirectToRoute('homepage');
}
PostController.php
/**
* #Route("/post/{id}", name="get_post")
*/
public function getPostAction(Post $post)
{
// Generate the comment form.
$comment = new Comment();
$form = $this->createForm(CommentType::class, $comment, [
'action' => $this->generateUrl('new_comment', ['post' => $post->getId()]),
]);
return $this->render('listeArticles.html.twig', [
'form' => $form->createView()
]);
}
CommentType.php
class CommentType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
//don't need to set the $post here
$builder
->add('content', TextareaType::class, [
'constraints' => [
new Assert\NotBlank(['message' => 'Your comment cannot be blank.']),
new Assert\Length([
'min' => 10,
'minMessage' => 'Your comment must be at least {{ limit }} characters long.',
]),
],
])
->add('submit', SubmitType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Comment::class
]);
}
}
With this you don't need to remove the Doctrine relationship between the two tables and manually set an ID.
Dont put in to form field,
for exampled
public function new(Request $request, UserInterface $user)
{
// 1) Build the form
$comment = new Comment();
$form = $this->createForm(CommentType::class, $comment);
// 2) Handle the submit (will only happen on POST)
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid())
{
comment->setPostId($post_id)
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($comment);
$entityManager->flush();
}
return $this->redirectToRoute('homepage');
}
The error message says it all:
Expected argument of type "App\Entity\Post or null", "string" given.
If you go to your comment Entity (App\Entity\Comment) you'll see that your class refers to the parent post as a Post Class (App\Entity\Post) and not as a "post_id".
It is the ORM (doctrine in this case) who does the link in your physical database and your Entity classes and add a post_id field in your table.
This is the what ORM (Object Relational Model) is for. You should no more consider Post and Comment as Sql tables but as Classes (OOP).
Thus is I want to add a comment related to someParent I should do something like:
$comment = new Comment();
$comment->setPost($post);
Where $post is an instance of the class Post.
I try to remove entities from a collection but it doesn't work.
I think I have a mistake somewhere, but I don't know where.
Here the code from my updateAction:
$em = $this->getDoctrine()->getEntityManager();
$entity = new Person();
if (!$entity) {
throw $this->createNotFoundException('Unable to find Person entity.');
}
$editForm = $this->createForm(new PersonType(), $entity);
$deleteForm = $this->createDeleteForm($id);
$request = $this->getRequest();
$editForm->bindRequest($request);
if ($editForm->isValid()) {
$entity = $editForm->getData();
$em->persist($entity);
foreach($entity->getAddresses() as $address)
{
$em->persist($address);
}
$em->flush();
return $this->redirect($this->generateUrl('person_show', array('id' => $id)));
}
return $this->render('AppPersonBundle:Person:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
);
Note that to remove my entity I remove the div from the html.
I mean I remove <div id="myapp_personbundle_persontype_address_4"> for example.
Is it the right way?
Thanks to this answer, I found a better solution. You can use Doctrine's orphan removal feature:
class Gallery
{
//...
/**
* #ORM\OneToMany(targetEntity="Photo", mappedBy="gallery", cascade={"persist", "remove"}, orphanRemoval=true)
*/
private $photos;
//...
public function removePhotos($photo)
{
$this->photos->remove($photo);
$photo->setGallery(null);
}
}
For now, i do :
[...]
$editForm = $this->createForm(new PersonType(), $entity);
$deleteForm = $this->createDeleteForm($id);
$previousCollections = array(
'addresses' => $entity->getAddresses(),
);
$request = $this->getRequest();
$editForm->bindRequest($request);
if ($editForm->isValid()) {
$entity = $editForm->getData();
$this->deleteCollections($em, $previousCollections, $entity);
$em->persist($entity);
foreach($entity->getAddresses() as $address)
{
$em->persist($address);
}
$em->flush();
return $this->redirect($this->generateUrl('person_show', array('id' => $id)));
}
[...]
}
private function deleteCollections($em, $init, $final)
{
if (empty($init)) {
return;
}
if (!$final->getAddresses() instanceof \Doctrine\ORM\PersistentCollection) {
foreach ($init['addresses'] as $addr) {
$em->remove($addr);
}
}
}
And I hope a solution will be found one day with https://github.com/symfony/symfony/issues/1540, but it slow to be found.
Form collection in symfony2 is quite straightforward, it does almost all the work for you. Basically you just need add a collection type and set allow_add, allow_delete flags and add a small JavaScript code. Have a look at the cookbook example
I'm using this solution...
In the controler:
$em = $this->getDoctrine()->getManager();
$enity->removeElements($em);
//Add all your elements again in order to update entity collection.
$entity->addElement($element) ...
....
$em->persist($entity);
$em->flush();
In the entity:
public function removeElements($em)
{
$elements = $this->elements;
foreach ($elements as $element) {
$this->elements->removeElement($element);
$em->remove($element);
$em->persist($this);
}
}
For me it works and it shows less code and I don't have to use the orphanRemoval feature.