I am trying to embed collection of Tag
forms to Service
form, according to this tutorial. Tag
and Service
entities have many-to-many relationship.
Form is rendering correctly. But when I submit form, I get
Could not determine access type for property "tagList"
error. I don't understand why new Tag
object is not added to the Service
class by calling the addTag()
method.
ServiceType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', TextType::class, array(
'label' => 'Title'
))
;
$builder->add('tagList', CollectionType::class, array(
'entry_type' => TagType::class,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false
)));
}
Service class
{
....
/**
* @ORM\ManyToMany(targetEntity="Tag", mappedBy="serviceList",cascade={"persist"})
*/
private $tagList;
/**
* @return ArrayCollection
*/
public function getTagList()
{
return $this->tagList;
}
/**
* @param Tag $tag
* @return Service
*/
public function addTag(Tag $tag)
{
if ($this->tagList->contains($tag) == false) {
$this->tagList->add($tag);
$tag->addService($this);
}
}
/**
* @param Tag $tag
* @return Service
*/
public function removeTag(Tag $tag)
{
if ($this->tagList->contains($tag)) {
$this->tagList->removeElement($tag);
$tag->removeService($this);
}
return $this;
}
}
Tag class
{
/**
* @ORM\ManyToMany(targetEntity="Service", inversedBy="tagList")
* @ORM\JoinTable(name="tags_services")
*/
private $serviceList;
/**
* @param Service $service
* @return Tag
*/
public function addService(Service $service)
{
if ($this->serviceList->contains($service) == false) {
$this->serviceList->add($service);
$service->addTag($this);
}
return $this;
}
/**
* @param Service $service
* @return Tag
*/
public function removeService(Service $service)
{
if ($this->serviceList->contains($service)) {
$this->serviceList->removeElement($service);
$service->removeTag($this);
}
return $this;
}
}
ServiceController
public function newAction(Request $request)
{
$service = new Service();
$form = $this->createForm('AppBundle\Form\ServiceType', $service);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($service);
$em->flush();
return $this->redirectToRoute('service_show', array('id' => $service->getId()));
}
return $this->render('AppBundle:Service:new.html.twig', array(
'service' => $service,
'form' => $form->createView(),
));
}
Maybe you forgot in the
__construct()
of Service class and Tag class to initialize $tagList and $serviceList like this ?$this->tagList = new ArrayCollection();
$this->serviceList = new ArrayCollection();
This seems like an error with your constructor. Try this :
Maybe the problem is that Symfony can't access that property?
If you look at where that exception is thrown (writeProperty method in the PropertyAccessor class) it says it can be thrown:
In the tutorial you mentioned it has property $tags, and method addTag. I'm just guessing here, but maybe there's a convention where it tries to call a method names
add($singularForm)
and this is failing for you because the property istagList
and the method isaddTag
.I'm not 100% sure, but you could try debugging by setting a stop point in that Symfony method to see why it's being thrown.
It's a long shot, but looking at your annotations I think the problem might be related to your manyToMany relationship. Try to change the owning side and inverse side (Swap the relationship) unless you specifically need to update from both ends (In that case I think the only solution is to add the objects manually or use oneToMany relationships).
This is a problem related to Doctrine I have suffered before, see: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/unitofwork-associations.html
If you are using symfony, and use EntityRepository instead of CollectionType, make sure you use the
'multiple' => true,
on your form build, otherwise the input will be for one entity and not for many, therefore it will call thesetTagList
instead of using the methodsaddTagList
andremoveTagList
.Could you please try to implement code from this URL?
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#owning-and-inverse-side-on-a-manytomany-association
First, please try to change mapped/inverse sides, and remove
$service->addTag($this);
fromTag::addService
method.