I use symfony6 for the first time with php 8.0.17. I want to make a small form that allows me to retrieve "Card" objects. My "Card" objects are bound to many to many color properties. I thought I could retrieve the cards objects via a findBy but I have the following error: Warning: Trying to access array offset on value of type null.
I looked at the documentation but I don't understand where my error comes from.
Cannot use findBy with related object ? Or maybe it's not a good idea to use entity field in form ? As you see the code is simple and it's that i don't understand it's not okay
The code is here :
My Card entity :
<?php
namespace App\Entity;
use App\Repository\CardRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity(repositoryClass: CardRepository::class)]
class Card
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\ManyToMany(targetEntity: Color::class, inversedBy: 'card')]
private $color;
public function __construct()
{
$this->color = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
/**
* #return Collection<int, Color>
*/
public function getColor(): Collection
{
return $this->color;
}
public function addColor(Color $color): self
{
if (!$this->color->contains($color)) {
$this->color[] = $color;
}
return $this;
}
public function removeColor(Color $color): self
{
$this->color->removeElement($color);
return $this;
}
}
My Color entity :
<?php
namespace App\Entity;
use App\Repository\ColorRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ColorRepository::class)]
class Color
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'string', length: 255)]
private $name;
#[ORM\ManyToMany(targetEntity: Card::class, mappedBy: 'color')]
private $card;
public function __construct()
{
$this->card = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function __toString()
{
return $this->getName();
}
/**
* #return Collection<int, Card>
*/
public function getCard(): Collection
{
return $this->card;
}
public function addCard(Cards $card): self
{
if (!$this->card->contains($card)) {
$this->card[] = $card;
$card->addColor($this);
}
return $this;
}
public function removeCard(Cards $card): self
{
if ($this->cards->removeElement($card)) {
$card->removeColor($this);
}
return $this;
}
}
My Search Form :
<?php
namespace App\Form;
use App\Entity\Color;
use App\Entity\Keyword;
use App\Entity\Type;
use App\Form\DataTransformer\ColorToStringTransformer;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
class CardSearchType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', TextType::class, ['required' => false])
->add('color', EntityType::class, [
'class' => Color::class,
// uses the Cards.name property as the visible option string
'choice_label' => 'name',
// used to render a select box, check boxes or radios
// 'multiple' => true,
// 'expanded' => true,
// To add little test for empty value
'placeholder' => 'Choose a color.',
'required' => false,
])
->add('save', SubmitType::class)
;
}
public function configureOptions(OptionsResolver $resolver): void
{
}
}
And to finish the controller action :
class DeckBuilderController extends AbstractController
{
#[Route('/deck/builder', name: 'app_deck_builder')]
public function index(Request $request, CardRepository $cardRepository): Response
{
$form = $this->createForm(CardSearchType::class);
$form->handleRequest($request);
$cards = null;
if ($form->isSubmitted() && $form->isValid())
{
// $form->getData() holds the submitted values
$cardData = $form->getData();
$cards = $cardRepository->findBy($cardData); => error Warning: Trying to access array offset on value of type null
}
return $this->render('deck_builder/index.html.twig', [
'controller_name' => 'DeckBuilderController',
'form' => $form->createView(),
'cards' => $cards,
]);
}
Thank in advance for your response.
$form->getData() doesn't return an array but an object with the form content.
My guess is that you want to use $form->get('color')->getData() instead
Correcting your code, I would try something like this :
public function index(Request $request, CardRepository $cardRepository): Response {
$cards = array();
$form = $this->createForm(CardSearchType::class);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$cards = $cardRepository->findBy(array('color'=>$form->get('color')->getData()));
}
return $this->renderForm('deck_builder/index.html.twig', array(
'controller_name' => 'DeckBuilderController',
'form' => $form,
'cards' => $cards,
));
}
To solve my problem I finally created a query by hand and made the join in DQL.
Related
Hello to the community,
I would like your help with two problems I am having with sending documents via my form and how I can display them in easyadmin please.
I've been stuck for some time on these two problems and all the answers I've found on the net haven't managed to get me out of this situation :'(
My documentsTypephp
<?php
namespace App\Form;
use App\Entity\Documents;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\VarDumper\Cloner\Data;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\File;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
class DocumentsType extends AbstractType
{
public function buildForm(
FormBuilderInterface $builder,
array $options
): void {
$builder
->add('description', TextType::class, [
'label' => 'Description',
'attr' => [
'placeholder' => 'Description',
],
])
->add('ui_ux', FileType::class, [
'multiple' => false,
'data_class' => null,
'label' => ' Si UX/ UI',
'mapped' => true,
'required' => false,
'empty_data' => '',
'constraints' => [
new File([
'maxSize' => '1024k',
'mimeTypes' => [
'application/pdf',
'application/x-pdf',
'application/doc',
'application/docx',
'application/figx',
'application/odt',
'application/ott',
'application/jpg',
],
'mimeTypesMessage' =>
'Please upload a valid PDF, document, Figma file',
]),
],
])
this is my documentsphp
<?php
namespace App\Entity;
use App\Repository\DocumentsRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: DocumentsRepository::class)]
class Documents
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column]
private ?\DateTime $sending_date = null;
#[ORM\ManyToOne(inversedBy: 'documents')]
#[ORM\JoinColumn(nullable: true)]
private ?User $users = null;
#[ORM\Column(type: Types::TEXT)]
private ?string $description = null;
#[ORM\Column(length: 400, nullable: true)]
private ?string $ui_ux = null;
#[ORM\Column(length: 400, nullable: true)]
private ?string $seo = null;
#[ORM\Column(length: 400, nullable: true)]
private ?string $image_service = null;
#[ORM\ManyToMany(targetEntity: Services::class, inversedBy: 'documents')]
private Collection $services;
public function __construct()
{
$this->services = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getSendingDate(): ?\DateTime
{
return $this->sending_date;
}
public function setSendingDate(\DateTime $sending_date): self
{
$this->sending_date = $sending_date;
return $this;
}
public function getUsers(): ?User
{
return $this->users;
}
public function setUsers(?User $users): self
{
$this->users = $users;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(string $description): self
{
$this->description = $description;
return $this;
}
public function getUiUx(): ?string
{
return $this->ui_ux;
}
public function setUiUx(?string $ui_ux): self
{
$this->ui_ux = $ui_ux;
return $this;
}
public function getSeo(): ?string
{
return $this->seo;
}
public function setSeo(?string $seo): self
{
$this->seo = $seo;
return $this;
}
public function getImageService(): ?string
{
return $this->image_service;
}
public function setImageService(?string $image_service): self
{
$this->image_service = $image_service;
return $this;
}
/**
* #return Collection<int, Services>
*/
public function getServices(): Collection
{
return $this->services;
}
public function addService(Services $service): self
{
if (!$this->services->contains($service)) {
$this->services->add($service);
}
return $this;
}
public function removeService(Services $service): self
{
$this->services->removeElement($service);
return $this;
}
}
and my second probleme realted to this one is how can i watch the documents in my easyadmin ?
I have this when i can send just one document
thank you very much indeed for your time to you all.
I've got a problem.
When I want to create an article, it shows me this error.
And when I want to edit one, it doesn't change anything.
It was working before, but then I've added category and comment section.
Can you help me ?
here is my Controller:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use App\Entity\Article;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ManagerRegistry;
use Doctrine\Persistence\ObjectManager;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension;
use Symfony\Component\Form\Forms;
use Symfony\Component\HttpFoundation\Request;
use App\Form\ArticleType;
class BlogController extends AbstractController
{
#[Route('/blog', name: 'blog')]
public function index(ManagerRegistry $doctrine): Response
{
$articles = $doctrine->getRepository(Article::class)->findAll();
return $this->render('blog/index.html.twig', [
'controller_name' => 'BlogController',
'articles' => $articles,
]);
}
#[Route("/", name: 'home')]
public function home() {
return $this->render('blog/home.html.twig', [
'title' => "Bienvenue",
'age' => 31,
]);
}
#[Route("/blog/new", name: 'blog_create')]
#[Route("/blog/{id}/edit", name: 'blog_edit')]
public function form(Article $article = null, Request $request, EntityManagerInterface $manager) {
// si on a pas d'article, donc on est en new
if(!$article){
$article = new Article();
}
$form = $this->createForm(ArticleType::class);
$form->handleRequest($request);
//si on a appuyer sur le bouton et que infos valides, on peut envoyer
if($form->isSubmitted() && $form->isValid()){
$manager->persist($article);
$manager->flush();
// on redirige vers l'article crée ou modifié
return $this->redirectToRoute('blog_show', ['id' => $article->getId()]);
}
return $this->render('blog/create.html.twig', [
'formArticle' => $form->createView(),
// edit Mode a true si il y a un article
'editMode' => $article->getId() !== null,
]);
}
#[Route("/blog/{id}", name: 'blog_show')]
public function show(ManagerRegistry $doctrine , $id){
$repo = $doctrine->getRepository(Article::class);
$article = $repo->find($id);
return $this->render('blog/show.html.twig', [
'article' => $article,
]);
}
}
And now, my form:
<?php
namespace App\Form;
use App\Entity\Article;
use App\Entity\Category;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
class ArticleType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('title')
->add('category', EntityType::class, [
'class' => Category::class,
'choice_label' => 'title',
])
->add('content')
->add('image')
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Article::class,
]);
}
}
To end with my Entities:
Article
<?php
namespace App\Entity;
use App\Repository\ArticleRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity(repositoryClass: ArticleRepository::class)]
class Article
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'string', length: 255)]
#[Assert\Length(
min: 2,
max: 50,
)]
private $title;
#[ORM\Column(type: 'text')]
private $content;
#[ORM\Column(type: 'string', length: 255)]
private $image;
#[ORM\ManyToOne(targetEntity: Category::class, inversedBy: 'articles')]
private $category;
#[ORM\OneToMany(mappedBy: 'article', targetEntity: Comment::class)]
private $comments;
public function __construct()
{
$this->comments = 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 getContent(): ?string
{
return $this->content;
}
public function setContent(string $content): self
{
$this->content = $content;
return $this;
}
public function getImage(): ?string
{
return $this->image;
}
public function setImage(string $image): self
{
$this->image = $image;
return $this;
}
public function getCategory(): ?Category
{
return $this->category;
}
public function setCategory(?Category $category): self
{
$this->category = $category;
return $this;
}
/**
* #return Collection<int, Comment>
*/
public function getComments(): Collection
{
return $this->comments;
}
public function addComment(Comment $comment): self
{
if (!$this->comments->contains($comment)) {
$this->comments[] = $comment;
$comment->setArticle($this);
}
return $this;
}
public function removeComment(Comment $comment): self
{
if ($this->comments->removeElement($comment)) {
// set the owning side to null (unless already changed)
if ($comment->getArticle() === $this) {
$comment->setArticle(null);
}
}
return $this;
}
}
Category
<?php
namespace App\Entity;
use App\Repository\CategoryRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: CategoryRepository::class)]
class Category
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'string', length: 255)]
private $title;
#[ORM\Column(type: 'text', nullable: true)]
private $description;
#[ORM\OneToMany(mappedBy: 'category', targetEntity: Article::class)]
private $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 getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): self
{
$this->description = $description;
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[] = $article;
$article->setCategory($this);
}
return $this;
}
public function removeArticle(Article $article): self
{
if ($this->articles->removeElement($article)) {
// set the owning side to null (unless already changed)
if ($article->getCategory() === $this) {
$article->setCategory(null);
}
}
return $this;
}
}
Thanks in advance guys :))
I won't add the twig file cause it's normal file
I succeeded.
In the controllers, I just added:
$this->createForm(ArticleType::class, $article);
I'm new to symfony and still learning, my question is how do I populate a select drop-down in a form with an static array of choices. Say I have a class named Cake, I'd like to be able to fill a drop-down for the status of Cake from the array statuses created in the same CakeEntity:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\CakeRepository")
*/
class Cake
{
/**
* #ORM\Column(type="string", length=50)
*/
private $status;
private $statuses = array(
'not_ready' => 'Not Ready',
'almost_ready' => 'Almost Ready',
'ready'=>'Ready',
'too_late'=>'Too late'
);
public function getStatus(): ?string
{
return $this->status;
}
public function setStatus(string $status): self
{
$this->status = $status;
return $this;
}
public function getStatuses()
{
return $this->statuses;
}
}
My Controller looks like:
namespace App\Controller;
use App\Entity\Cake;
use App\Form\CakeType;
use App\Repository\CakeRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* #Route("/cake")
*/
class CakeController extends AbstractController
{
/**
* #Route("/new", name="cake_new", methods={"GET","POST"})
*/
public function new(Request $request): Response
{
$cake = new Cake();
$form = $this->createForm(CakeType::class, $cake);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$cake->setCreatedAt(\DateTime::createFromFormat('d-m-Y', date('d-m-Y')));
$cake->setCreatedBy(1);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($cake);
$entityManager->flush();
return $this->redirectToRoute('cake_index');
}
return $this->render('cake/new.html.twig', [
'cake' => $cake,
'form' => $form->createView(),
]);
}
My CakeEntity:
<?php
namespace App\Form;
use App\Entity\cake;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
class CakeType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
->add('status', ChoiceType::class,
[
'choices'=>function(?Cake $cake) {
return $cake->getStatuses();
}
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Cake::class,
]);
}
}
When trying to browse /cake/new I get the error:
An error has occurred resolving the options of the form "Symfony\Component\Form\Extension\Core\Type\ChoiceType": The option "choices" with value Closure is expected to be of type "null" or "array" or "\Traversable", but is of type "Closure".
You could declare getStatuses on Cake as static, or use public constants. E.g.:
class Cake
{
// with static variables
private static $statuses = [
'not_ready' => 'Not Ready',
'almost_ready' => 'Almost Ready',
'ready' => 'Ready',
'too_late' => 'Too late',
];
public static function getStatuses()
{
return self::$statuses;
}
// or with public const
public const STATUSES = [
'not_ready' => 'Not Ready',
'almost_ready' => 'Almost Ready',
'ready' => 'Ready',
'too_late' => 'Too late',
];
}
This seems reasonable, as the return value is not instance but class specific.
You could then use:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('status', ChoiceType::class, [
'choices'=> Cake::getStatuses(),
]);
// or
$builder->add('status', ChoiceType::class, [
'choices'=> Cake::STATUSES,
]);
}
If the choices actually depend on a given Cake instance, you could pass it via the options array or use form events.
I am doing a crud for an entity in my application. The form have to upload a file, so i added the assert in the entity file. But when i submit my form the validator give me an error and said to me that the field image have to be a string. I've done upload of file a hundred times, that why i don't understand this time why the validator bundles react like that.
My entity:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity(repositoryClass="App\Repository\AlgorithmeRepository")
*/
class Algorithme
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $titre;
/**
* #ORM\Column(type="date")
*/
private $dateCreationArticle;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*
* #Assert\File(mimeTypes={ "image/jpeg","image/png"})
*/
private $image;
/**
* #ORM\Column(type="array")
*/
private $analyse = [];
public function getId(): ?int
{
return $this->id;
}
public function getTitre(): ?string
{
return $this->titre;
}
public function setTitre(string $titre): self
{
$this->titre = $titre;
return $this;
}
public function getDateCreationArticle(): ?\DateTimeInterface
{
return $this->dateCreationArticle;
}
public function setDateCreationArticle(\DateTimeInterface $dateCreationArticle): self
{
$this->dateCreationArticle = $dateCreationArticle;
return $this;
}
public function getImage()
{
return $this->image;
}
public function setImage($image)
{
$this->image = $image;
return $this;
}
public function getAnalyse(): ?array
{
return $this->analyse;
}
public function setAnalyse(array $analyse): self
{
$this->analyse = $analyse;
return $this;
}
}
The form :
<?php
namespace App\Form;
use App\Entity\Algorithme;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class AlgorithmeType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('titre')
->add('dateCreationArticle',DateType::class,[
'widget' => 'single_text',
// prevents rendering it as type="date", to avoid HTML5 date pickers
'html5' => false,
// adds a class that can be selected in JavaScript
'attr' => ['class' => 'js-datepicker'],
])
->add('image',FileType::class,[
'required' => false,
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Algorithme::class,
]);
}
}
And the controller:
<?php
namespace App\Controller;
use App\Entity\Algorithme;
use App\Form\AlgorithmeType;
use App\Repository\AlgorithmeRepository;
use App\Services\CreateFormForArray;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* #Route("/algorithme")
*/
class AlgorithmeController extends AbstractController
{
/**
* #Route("/new", name="algorithme_new", methods={"GET","POST"})
*/
public function new(Request $request): Response
{
$algorithme = new Algorithme();
$form = $this->createForm(AlgorithmeType::class, $algorithme);
$form->handleRequest($request);
// die();
if ($form->isSubmitted() && $form->isValid()) {
$entityManager = $this->getDoctrine()->getManager();
$CreateFormForArray = new CreateFormForArray();
$CreateFormForArray->handleArrayString($request,$algorithme,"analyse");
$entityManager->persist($algorithme);
$entityManager->flush();
return $this->redirectToRoute('algorithme_index');
} else {
}
return $this->render('algorithme/new.html.twig', [
'algorithme' => $algorithme,
'form' => $form->createView(),
]);
}
}
I found the problem for those who will wondering is was
#auto_mapping:
# App\Entity\: []
that was uncomment in config/packages/validator.yaml
I have a problem when I try to embed a form in Symfony2 for many to many relations or many to one relations.
I have two entities called 'Address' and 'AddressType' and they are related as you can see on code below.
What I tried to do is when I created a form for Address, I embedded the form for AddressType. I've already tried embedding a collection of AddressType to Address form, but when I try to embed the result of this to Address it seems not to work.
Address Entity
namespace Webmuch\ProductBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity
*/
class Address
{
protected $id;
protected $line1;
protected $line2;
protected $state;
protected $city;
protected $zip;
protected $country;
protected $phone;
/**
* #ORM\ManyToOne(targetEntity="AddressType")
* #ORM\JoinColumn(name="address_type_id", referencedColumnName="id")
*/
protected $type;
public function __construct()
{
$this->type = new ArrayCollection();
}
/**
* Set type
*
* #param Webmuch\ProductBundle\Entity\AddressType $type
*/
public function setType(\Webmuch\ProductBundle\Entity\AddressType $type)
{
$this->type = $type;
}
/**
* Get type
*
* #return Webmuch\ProductBundle\Entity\AddressType
*/
public function getType()
{
return $this->type;
}
}
AddressType Entity:
namespace Webmuch\ProductBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
*/
class AddressType
{
protected $id;
protected $title;
public function __construct()
{
$this->title = false;
}
}
In form section->
form
AddressType:
namespace Webmuch\AdminBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
class AddressType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('line1')
->add('line2')
->add('city')
->add('zip')
->add('country')
->add('phone')
->add('type','collection', array( 'type' => new AddressTypeType(),
'allow_add' => true,
'prototype' => true,
'by_reference' => false,
));
}
public function getDefaultOptions(array $options)
{
return array('data_class' => 'Webmuch\ProductBundle\Entity\Address');
}
public function getName()
{
return 'address';
}
}
AddressTypeType:
namespace Webmuch\AdminBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
class AddressTypeType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('title');
;
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => 'Webmuch\ProductBundle\Entity\AddressType',
);
}
public function getName()
{
return 'addresstypetype';
}
}
Controller Section->
namespace Webmuch\AdminBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Webmuch\ProductBundle\Entity\Address;
use Webmuch\AdminBundle\Form\AddressType;
/**
* Address controller.
*
* #Route("/cusadmin/address")
*/
class AddressController extends Controller
{
/**
* Displays a form to create a new Address entity.
*
* #Route("/new", name="admin_address_new")
* #Template()
*/
public function newAction()
{
$entity = new Address();
$form = $this->createForm(new AddressType(), $entity);
return array(
'entity' => $entity,
'form' => $form->createView()
);
}
}
I've spent the whole day stuck with this and I have tried a lot of things but I couldn't manage get it working.
Any help is appreciated!
Thanks
Edit form AddressType: nd write this code,may be this is help full....
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('line1')
->add('line2')
->add('city')
->add('zip')
->add('country')
->add('phone')
->add('type','entity', array('class'=>'WebmuchProductBundle:AddressType','property'=>'value','multiple'=>true
));