I am new to Symfony 4 and I am following this tutorial "https://symfony.com/doc/4.4/forms.html" but it does not recognize my variable "form" and I don't know why (everything is up to date).
My Controller :
<?php
namespace App\Controller;
use App\Entity\Task;
use App\Form\Type\TaskType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
class TaskController extends AbstractController
{
public function new(Request $request)
{
// creates a task object and initializes some data for this example
$task = new Task();
$task->setTask('Write a blog post');
$task->setDueDate(new \DateTime('tomorrow'));
/*$form = $this->createFormBuilder($task)
->add('task', TextType::class)
->add('dueDate', DateType::class)
->add('save', SubmitType::class, ['label' => 'Create Task'])
->setMethod('GET')
->getForm();*/
$form = $this->createForm(TaskType::class, $task);
return $this->render('search/search.html.twig', [
'form' => $form->createView(),
]);
}
}
My TaskType.php :
<?php
namespace App\Form\Type;
use App\Entity\Task;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
class TaskType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('task', TextType::class)
->add('dueDate', DateType::class)
->add('save', SubmitType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Task::class,
]);
}
}
And my Task.php :
<?php
namespace App\Entity;
class Task
{
protected $task;
protected $dueDate;
public function getTask()
{
return $this->task;
}
public function setTask($task)
{
$this->task = $task;
}
public function getDueDate()
{
return $this->dueDate;
}
public function setDueDate(\DateTime $dueDate = null)
{
$this->dueDate = $dueDate;
}
}
If you see any error from my part I am open..
I am calling my form here :
{{ form_start(form) }}
{{ form(form) }}
{{ form_end(form) }}
In my "search.html.twig".
Related
I'm using Symfony 6.
I have 2 entities 'Article' and 'Picture', with a ManyToMany relationship between both (ie : an Article can have several Picture(s), a Picture can belong to several Article(s));
I made a CRUD:Article and a CRUD:Picture.
Now I when I create a new Article via the form, I would like to have the ability to select what Picture(s) I want to put in my new Article. But I cannot find a way to do that. In the form I only have add->('pictures') in the $builder I can't figure how to set the field to have something like a choiceType where I could select what Picture I want, then save the Article and save the resulting line in the join table...
Any help would be appreciated :)
Sorry for my english (not my native language)
Here my Article entity
namespace App\Form;
use App\Entity\Article;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ArticleType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('title')
->add('chapo')
->add('content')
->add('pictures')
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Article::class,
]);
}
}
And my Picture entity:
namespace App\Entity;
use App\Repository\PictureRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: PictureRepository::class)]
class Picture
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $title = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $altText = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $maxWidth = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $minWidth = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $maxHeight = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $minHeight = null;
#[ORM\Column(length: 255)]
private ?string $picture = null;
#[ORM\ManyToMany(targetEntity: Article::class, mappedBy: 'pictures')]
private Collection $articles;
public function __construct()
{
$this->articles = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
public function getAltText(): ?string
{
return $this->altText;
}
public function setAltText(?string $altText): self
{
$this->altText = $altText;
return $this;
}
public function getMaxWidth(): ?string
{
return $this->maxWidth;
}
public function setMaxWidth(?string $maxWidth): self
{
$this->maxWidth = $maxWidth;
return $this;
}
public function getMinWidth(): ?string
{
return $this->minWidth;
}
public function setMinWidth(?string $minWidth): self
{
$this->minWidth = $minWidth;
return $this;
}
public function getMaxHeight(): ?string
{
return $this->maxHeight;
}
public function setMaxHeight(?string $maxHeight): self
{
$this->maxHeight = $maxHeight;
return $this;
}
public function getMinHeight(): ?string
{
return $this->minHeight;
}
public function setMinHeight(?string $minHeight): self
{
$this->minHeight = $minHeight;
return $this;
}
public function getPicture(): ?string
{
return $this->picture;
}
public function setPicture(string $picture): self
{
$this->picture = $picture;
return $this;
}
/**
* #return Collection<int, Article>
*/
public function getArticles(): Collection
{
return $this->articles;
}
public function addArticle(Article $article): self
{
if (!$this->articles->contains($article)) {
$this->articles->add($article);
$article->addPicture($this);
}
return $this;
}
public function removeArticle(Article $article): self
{
if ($this->articles->removeElement($article)) {
$article->removePicture($this);
}
return $this;
}
}
And my Form :
namespace App\Form;
use App\Entity\Article;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ArticleType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('title')
->add('chapo')
->add('content')
->add('pictures')
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Article::class,
]);
}
}
Finally the controllers
PictureController
namespace App\Controller;
use App\Entity\Picture;
use App\Form\PictureType;
use App\Repository\PictureRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
#[Route('/picture')]
class PictureController extends AbstractController
{
#[Route('/', name: 'app_picture_index', methods: ['GET'])]
public function index(PictureRepository $pictureRepository): Response
{
return $this->render('picture/index.html.twig', [
'pictures' => $pictureRepository->findAll(),
]);
}
#[Route('/new', name: 'app_picture_new', methods: ['GET', 'POST'])]
public function new(Request $request, PictureRepository $pictureRepository,EntityManagerInterface $entityManager): Response
{
$picture = new Picture();
$form = $this->createForm(PictureType::class, $picture, ['add' => true]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$pict = $form->get('picture')->getData();
if($pict)
{
$nomPicture = date('YmdHis') . "-" . uniqid() . "." . $pict->getClientOriginalExtension();
$pict->move(
$this->getParameter('pictures_directory'),
$nomPicture
);
$picture->setPicture($nomPicture);
}
$entityManager->persist($picture);
$entityManager->flush();
$pictureRepository->add($picture, true);
return $this->redirectToRoute('app_picture_index', [], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('picture/new.html.twig', [
'picture' => $picture,
'form' => $form,
]);
}
#[Route('/{id}', name: 'app_picture_show', methods: ['GET'])]
public function show(Picture $picture): Response
{
return $this->render('picture/show.html.twig', [
'picture' => $picture,
]);
}
#[Route('/{id}/edit', name: 'app_picture_edit', methods: ['GET', 'POST'])]
public function edit(Request $request, Picture $picture, PictureRepository $pictureRepository): Response
{
$form = $this->createForm(PictureType::class, $picture);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$pictureRepository->add($picture, true);
return $this->redirectToRoute('app_picture_index', [], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('picture/edit.html.twig', [
'picture' => $picture,
'form' => $form,
]);
}
#[Route('/{id}', name: 'app_picture_delete', methods: ['POST'])]
public function delete(Request $request, Picture $picture, PictureRepository $pictureRepository): Response
{
if ($this->isCsrfTokenValid('delete'.$picture->getId(), $request->request->get('_token'))) {
$pictureRepository->remove($picture, true);
}
return $this->redirectToRoute('app_picture_index', [], Response::HTTP_SEE_OTHER);
}
}
ArticleController
namespace App\Controller;
use App\Entity\Article;
use App\Form\ArticleType;
use App\Repository\ArticleRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
#[Route('/article')]
class ArticleController extends AbstractController
{
#[Route('/', name: 'app_article_index', methods: ['GET'])]
public function index(ArticleRepository $articleRepository): Response
{
return $this->render('article/index.html.twig', [
'articles' => $articleRepository->findAll(),
]);
}
#[Route('/new', name: 'app_article_new', methods: ['GET', 'POST'])]
public function new(Request $request, ArticleRepository $articleRepository): Response
{
$article = new Article();
$form = $this->createForm(ArticleType::class, $article);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$articleRepository->add($article, true);
return $this->redirectToRoute('app_article_index', [], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('article/new.html.twig', [
'article' => $article,
'form' => $form,
]);
}
#[Route('/{id}', name: 'app_article_show', methods: ['GET'])]
public function show(Article $article): Response
{
return $this->render('article/show.html.twig', [
'article' => $article,
]);
}
#[Route('/{id}/edit', name: 'app_article_edit', methods: ['GET', 'POST'])]
public function edit(Request $request, Article $article, ArticleRepository $articleRepository): Response
{
$form = $this->createForm(ArticleType::class, $article);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$articleRepository->add($article, true);
return $this->redirectToRoute('app_article_index', [], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('article/edit.html.twig', [
'article' => $article,
'form' => $form,
]);
}
#[Route('/{id}', name: 'app_article_delete', methods: ['POST'])]
public function delete(Request $request, Article $article, ArticleRepository $articleRepository): Response
{
if ($this->isCsrfTokenValid('delete'.$article->getId(), $request->request->get('_token'))) {
$articleRepository->remove($article, true);
}
return $this->redirectToRoute('app_article_index', [], Response::HTTP_SEE_OTHER);
}
}
I'm making a form to register books (Symfony 4), each with a unique publisher (ManyToOne) and one or many authors (ManyToMany). Both fields are filled in the form as tags, with Bootstrap TagsInput, so that if the user types in those fields, they will suggest the list of values in the DB tables, and if not, the new values will be inserted when submitting, along with the other book data.
I followed the official example of Best Practices on the Symfony website, and the tagging system works for authors, because it's a CollectionType, but not with the publisher, because it's an EntityType. How could I adapt it? Fails to transform publisher values into comma-separated strings so it can be recognized by TagsInput.
Book Entity (App\Entity\Book.php)
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
class Book
{
/**
* #var \Publisher
*
* #ORM\ManyToOne(targetEntity="Publisher", cascade={"persist"})
* #ORM\JoinColumns({
* #ORM\JoinColumn(nullable=false, name="publisher_id", referencedColumnName="id")
* })
*/
private $publisher;
/**
* #var Author[]|ArrayCollection
*
* #ORM\ManyToMany(targetEntity="Author", cascade={"persist"})
* #ORM\JoinTable(name="authors_books")
*/
private $authors;
public function __construct()
{
$this->authors = new ArrayCollection();
}
public function getPublisher()
{
return $this->publisher;
}
public function getAuthors(): Collection
{
return $this->authors;
}
}
Book Form (App\Form\BookType.php)
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use App\Form\Type\PublisherType;
use App\Form\Type\AuthorType;
class BookType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options){
$builder
->add('publisher', PublisherType::class, array(
'label' => 'Publisher',
))
->add('authors', AuthorType::class, array(
'label' => 'Author/s'
))
}
}
AuthorType
namespace App\Form\Type;
use Symfony\Bridge\Doctrine\Form\DataTransformer\CollectionToArrayTransformer;
use App\Form\DataTransformer\AuthorToStringTransformer;
use App\Repository\AuthorRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
class AuthorType extends AbstractType {
private $authors;
public function __construct(AuthorRepository $authors_repo)
{
$this->authors = $authors_repo;
}
public function buildForm(FormBuilderInterface $builder, array $options){
$builder
->addModelTransformer(new CollectionToArrayTransformer(), true)
->addModelTransformer(new AuthorToStringTransformer($this->authors), true)
;
}
public function buildView(FormView $view, FormInterface $form, array $options): void
{
$view->vars['authors'] = $this->authors->findAll();
}
public function getParent()
{
return TextType::class;
}
}
PublisherType
namespace App\Form\Type;
use App\Form\DataTransformer\EntityToArrayTransformer;
use App\Form\DataTransformer\PublisherToStringTransformer;
use App\Repository\PublisherRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
class PublisherType extends AbstractType {
private $publishers;
public function __construct(PublisherRepository $publisher_repo) {
$this->publishers = $publisher_repo;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->addModelTransformer(new EntityToArrayTransformer(), true)
->addModelTransformer(new PublisherToStringTransformer($this->publishers), true);
}
public function buildView(FormView $view, FormInterface $form, array $options): void
{
$publishers = $this->publishers->findAll();
}
public function getParent()
{
return TextType::class;
}
}
CollectionToArrayTransformer
namespace Symfony\Bridge\Doctrine\Form\DataTransformer;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Symfony\Component\Form\DataTransformerInterface;
class CollectionToArrayTransformer implements DataTransformerInterface
{
public function transform($collection)
{
if (null === $collection) {
return [];
}
if (\is_array($collection)) {
return $collection;
}
return $collection->toArray();
}
}
EnityToArrayTransformer
namespace App\Form\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
class EntityToArrayTransformer implements DataTransformerInterface
{
public function transform($entity)
{
if (null === $entity) {
return [];
}
return [$entity];
}
}
AuthorToStringTransformer
namespace App\Form\DataTransformer;
use App\Entity\Author;
use App\Repository\AuthorRepository;
use Symfony\Component\Form\DataTransformerInterface;
class AuthorToStringTransformer implements DataTransformerInterface
{
private $authors;
public function __construct(AuthorRepository $authors)
{
$this->authors = $authors;
}
public function transform($authors): string
{
/* #var Author[] $authors */
return implode(',', $authors);
}
public function reverseTransform($string): array
{
...
}
}
PublisherToStringTransformer
namespace App\Form\DataTransformer;
use App\Entity\Publisher;
use App\Repository\PublisherRepository;
use Symfony\Component\Form\DataTransformerInterface;
class PublisherToStringTransformer implements DataTransformerInterface
{
private $publishers;
public function __construct(PublisherRepository $publishers)
{
$this->publishers = $publishers;
}
public function transform($publisher): string
{
/* #var Publisher[] $publisher */
return implode(',', $publisher);
}
public function reverseTransform($publisher): string
{
...
}
}
Form Twig
{{ form_widget(form.publisher, {'attr': {'class': class, 'data-toggle': 'tagsinput', 'data-publishers': form.publisher.vars.publishers|json_encode } }) }}
{{ form_widget(form.publisher, {'attr': {'class': class, 'data-toggle': 'tagsinput', 'data-authors': form.publisher.vars.authors|json_encode } }) }}
This is the code I use for Editors and Authors, so that you can compare the one that works and the one that doesn't work. They are not so different, but something is wrong, and I don't know what it is or what I need to change.
Ok, I've found a solution. I have made all the changes in both Transformers, because the problem was the format to which I converted the entity and vice versa.
General info
I am working with Symfony 2.8. In this question two entities are the subject. ObjectElementTask and Activity. I have embedded Activity as a collection inside ObjectElementTask. So far, everything is fine and up and running.
Problem
I added a evenlistener in ActivityType. Because a part of the ActivityForm inside the ObjectElementTaskForm has to be dynamic (based on the authenticated user that is using the form...)
When I view the ActivityForm direct: through the ActivityController (which calls the form with this code: $editForm = $this->createForm('AppBundle\Form\ActivityType', $activity);) the eventlistener is working.
When I view the ObjectElementTaksForm I get a exception:
Type error: Argument 1 passed to AppBundle\Form\ActivityType::__construct() must implement interface Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface, none given, called in /home/vpcont1q/public_html/test/src/AppBundle/Form/ObjectElementTaskType.php on line 62
My Guess
I guess because inside the ObjectElementTaksForm, the ActivityForm gets called on a other way then inside the ActivityController. And then the argument (registered in the services.yml) doesn't get passed. How to make sure the registered service gets called when embedding the form? Or... am I looking in the wrong direction.
Code
Below my Types and the services.yml part:
This is my ActivityType:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
class ActivityType extends AbstractType
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('executionDate')
->add('status'),
->add('scheduledDate')
// grab the user, do a quick sanity check that one exists
$user = $this->tokenStorage->getToken()->getUser();
if (!$user) {
throw new \LogicException(
'You are NOT an authenticated user!'
);
}
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($user) {
//TODO
});
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Activity'
));
}
}
And this is my ObjectElementTaskType:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
class ObjectElementTaskType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('activities', 'collection', array(
'entry_type' => new ActivityType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
))
;
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\ObjectElementTask',
));
}
}
I have registered the ActivityForm as a service with the token as a argument:
app.form.activity:
class: AppBundle\Form\ActivityType
arguments: ['#security.token_storage']
tags:
- { name: form.type }
EDIT
This seems to work:
Instead of registering the ActivityType as a service I registered the ObjectElementTask as a service (also with the Tokenstorage).
I don't use the ActivityType other then embedded in the ObjectElementTaskType so that's why I removed the ActivityType as a service in services.yml.
app.form.object_element_task:
class: AppBundle\Form\ObjectElementTaskType
arguments: ['#security.token_storage']
tags:
- { name: form.type }
And in the ObjectElementTaskType I added the construct:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
class ObjectElementTaskType extends AbstractType
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$tokenStorage = $this->tokenStorage;
And in the buildform I added the tokenstorage as a parameter in the ActivityType class declaration:
->add('activities', 'collection', array(
'entry_type' => new ActivityType($tokenStorage),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
))
The ActivityType I haven't changed. Is this a workaround or the way to do it?
I know that could be a noob error, but I wasted a lot of time in this.
I have a entity that modified with a form. This is my entity:
class RetiroResiduo
{
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="GestionResiduos\SolicitudRetiroBundle\Entity\SolicitudRetiro")
* #ORM\JoinColumn(name="numeroSolicitudRet_id", onDelete="CASCADE", referencedColumnName="numeroSolicitudRet")
*/
protected $numeroSolicitudRet;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="GestionResiduos\ResiduoBundle\Entity\Residuo")
* #ORM\JoinColumn(name="siglaRepresentativa_id", onDelete="CASCADE",referencedColumnName="siglaRepresentativa")
*/
protected $siglaRepresentativa;
/**
* #ORM\ManyToOne(targetEntity="GestionResiduos\ResiduoBundle\Entity\Contenedor")
* #ORM\JoinColumn(name="nombreContenedor_id", onDelete="CASCADE", referencedColumnName="nombreContenedor")
*/
protected $nombreContenedor;
...
}
This entity is handled with this form:
<?php
// src/Gestionresiudos/SolicitudRetiroBundle/Form/SolicitudRetiroType.php
namespace Gestionresiduos\SolicitudRetiroBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class RetiroResiduoType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('siglaRepresentativa')
->add('nombreContenedor')
->add('cantidadContenedores')
->add('peso')
->add('volumen')
->add('solicitar', 'submit')
->add('addotro', 'submit')
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Gestionresiduos\SolicitudRetiroBundle\Entity\RetiroResiduo',
'cascade_validation' => true,
));
}
public function getName()
{
return 'retiroresiduo';
}
}
my action into my controller look like:
public function RetirarResiduoAction($idsol, Request $request)
{
$numSolRetiro = $idsol;
$residuoARetirar = new RetiroResiduo();
//echo gettype($residuoARetirar);
$formulario = $this->createForm(new RetiroResiduoType(), $residuoARetirar);
$formulario->handleRequest($request);
if ($formulario->isValid())
{
....
}
...
}
This is my form into view:
{{ form_start(formulario, {'attr': {'class': 'form-horizontal'}})}}
{{ form_errors(formulario)}}
{{ form_rest(formulario) }}
{{ form_end(formulario)}}
Finally I give you a print from the error to give my interface.
As you can see when I send my form doesn't enter into if(formulario->isvalid()). Obviously, I selected one option into choice. I saw similar questions but don't working for me. I need some advice or something that help me with this bug.
Note: I know that problem should be into my entity but I still don't see.
NOTE2: I'm using symfony2.3
I have 2 entities: Audio and Destination
In Audio:
/**
* #ORM\OneToOne(targetEntity="HearWeGo\HearWeGoBundle\Entity\Destination", inversedBy="audio")
* #Assert\NotBlank(message="This field must be filled")
*
*/
private $destination;
I created a Form Type name EditAudioType used to edit an audio whose uploaded link is stored in database
<?php
namespace HearWeGo\HearWeGoBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use HearWeGo\HearWeGoBundle\Entity\Audio;
class AudioAudioType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$destination_repo=$options['dr'];
$builder
->add('name','text')
->add('audio','file')
->add('destination','entity',array(
'class'=>'HearWeGoHearWeGoBundle:Destination',
'choices'=>$destination_repo->findToReplaceAudio('id'),
'property'=>'name'
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array('data_class'=>"HearWeGo\\HearWeGoBundle\\Entity\\Audio"));
$resolver->setRequired(array('dr'));
}
public function getName()
{
return 'edit_audio';
}
}
I did as the similar answer in my old post:
Symfony2 Entity Form Type gets data
But now I don't know what I will put in choices attribute of form, because this custom repo function has parameter, not like the old answer. In DestinationRepository:
public function findByAudioId($id)
{
return $this->getEntityManager()->createQuery('SELECT d FROM HearWeGoHearWeGoBundle:Destination d,HearWeGoHearWeGoBundle:Audio a WHERE d.id=IDENTITY (a.destination)')->getResult();
}
public function findToReplaceAudio($id)
{
$result=$this->findDestinationWithoutAudio();
$result[]=$this->findByAudioId($id);
return $result;
}
I'll do something like :
<?php
namespace HearWeGo\HearWeGoBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use HearWeGo\HearWeGoBundle\Entity\Audio;
use HearWeGo\HearWeGoBundle\Entity\Repository\AudioRepository;
class AudioAudioType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name','text')
->add('audio','file')
->add('destination','entity',array(
'class'=>'HearWeGoHearWeGoBundle:Destination',
'query_builder'=>function (AudioRepository $repository) {
return $repository->findToReplaceAudioQueryBuilder('id');
},
'property' => 'name'
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array('data_class'=>"HearWeGo\\HearWeGoBundle\\Entity\\Audio"));
}
public function getName()
{
return 'edit_audio';
}
}
Please have a look to the official documentation.