tutorial symfony2 query generate entitymanagerinterface consultas doctrine-orm symfony symfony-forms

doctrine-orm - symfony2 - symfony 3.4 doctrine query



Incrustar un error de colección de formularios: no se pudo determinar el tipo de acceso para la propiedad (7)

Estoy intentando incrustar la colección de formularios de Tag formulario de Service , de acuerdo con este tutorial . Service entidades de Tag y Service tienen una relación de muchos a muchos.

La forma se está procesando correctamente. Pero cuando envío el formulario, me sale

No se pudo determinar el tipo de acceso para la propiedad "tagList"

error. No entiendo por qué el nuevo objeto Tag no se agrega a la clase de Service llamando al método addTag() .

Tipo de servicio

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 ))); }

Clase de servicio

{ .... /** * @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; } }

Clase de etiqueta

{ /** * @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; } }

Controlador de servicio

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(), )); }



¿Tal vez se olvidó en __construct() de la clase de servicio y la clase de etiqueta para inicializar $ tagList y $ serviceList así?

$this->tagList = new ArrayCollection();

$this->serviceList = new ArrayCollection();


Es una posibilidad remota, pero mirando sus anotaciones, creo que el problema podría estar relacionado con su relación manyToMany. Intente cambiar el lado propietario y el lado inverso (Intercambiar la relación) a menos que específicamente necesite actualizar desde ambos extremos (en ese caso, creo que la única solución es agregar los objetos manualmente o usar las relaciones oneToMany).

Los cambios realizados solo en el lado inverso de una asociación se ignoran. Asegúrate de actualizar ambos lados de una asociación bidireccional (o al menos el lado propietario, desde el punto de vista de Doctrine)

Este es un problema relacionado con la Doctrina que he sufrido anteriormente, consulte: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/unitofwork-associations.html


Esto parece un error con tu constructor. Prueba esto :

public function __construct() { $this-> tagList = new /Doctrine/Common/Collections/ArrayCollection(); }


Tal vez el problema es que Symfony no puede acceder a esa propiedad?

Si observa dónde se produce esa excepción (método writeProperty en la clase PropertyAccessor), dice que se puede lanzar:

Si la propiedad no existe o no es pública.

En el tutorial que mencionaste tiene propiedades $ tags, y el método addTag. Solo estoy adivinando aquí, pero tal vez hay una convención donde intenta llamar a los nombres de un método add($singularForm) y esto está fallando porque la propiedad es tagList y el método es addTag .

No estoy 100% seguro, pero puedes intentar depurar estableciendo un punto de parada en ese método de Symfony para ver por qué se está lanzando.


Basado en Symfony 3.3.10

Realmente enfrenté este problema muchas y muchas veces, finalmente, una vez que descubrí de dónde venía este problema, dependiendo del nombre que le dé a la propiedad de su entidad, puede suceder que el sumador y el removedor de su propiedad de colección no sean exactamente lo que usted están esperando

Ejemplo: el nombre de la propiedad de su entidad es "foo" y usted esperaría que el sumador se llame "addFoo" y el removedor "removeFoo", pero de repente aparece el mensaje "No se pudo determinar el tipo de acceso para la propiedad" .

Así que empiezas a tener miedo al buscar problemas w / e en tu código, en vez de eso solo tienes que buscar este archivo dentro de los archivos principales de Symfony:

proveedor / symfony / symfony / src / Symfony / Component / PropertyAccess / PropertyAccessor.php

Dentro de este archivo hay un método llamado findAdderAndRemover . Vaya allí con su depurador y finalmente descubrirá que Symfony busca un nombre extraño para su agregador / removedor, que en realidad terminarán con "um" o "on" o "us" dependiendo del idioma (lenguaje humano) que usó para nómbralos. Ya que soy italiano esto sucede muy a menudo.

Tenga cuidado con eso, ya que la solución puede ser tan simple como cambiar el nombre utilizado para su método de agregar / eliminar dentro de su entidad para que coincidan con lo que el núcleo de Symfony está buscando.

Esto me sucede cuando uso la doctrina bin / console: generar: entidades para crear los métodos automáticamente para mí


Version corta:

Acabo de encontrarme con este problema y lo resolví agregando un setter para la propiedad afectada:

No se pudo determinar el tipo de acceso para la propiedad "tagList"

public function setTagList(Array $tagList) { $this->tagList = $tagList; }

Versión larga:

El mensaje de error indica que Symfony está intentando modificar el estado del objeto, pero no puede averiguar cómo realizar el cambio debido a la forma en que está configurada su clase.

Echando un vistazo a las partes internas de Symfony , podemos ver que Symfony le brinda 5 oportunidades para darle acceso y elige la mejor en este orden de arriba a abajo:

  1. Un método de establecimiento llamado setProperty() con un argumento:

Esto es lo primero que Symfony comprueba y es la forma más explícita de lograrlo. Por lo que yo sé, esta es la mejor práctica:

class Entity { protected $tagList; //... public function getTagList() { return $this->tagList; } //... }

  1. Un combinador y definidor en un método con un argumento:

Es importante darse cuenta de que Symfony también tendrá acceso a este método para obtener el estado del objeto. Como esas llamadas de método no incluyen un argumento, el argumento de este método debe ser opcional.

class Entity { protected $tagList; //... public function tagList($tags = null) { if($reps){ $this->tagList = $tags; } else { return $this->tagList; } } //... }

  1. La propiedad afectada se declara como pública:

    class Entity { public $tagList; //... other properties here }

  2. Un método mágico __set :

Esto afectará todas las propiedades en lugar de solo la que usted deseaba.

class Entity { public $tagList; //... public function __set($name, $value){ $this->$name = $value; } //... }

  1. Un método mágico __call (en algunos casos):

No pude confirmar esto, pero el código interno sugiere que esto es posible cuando la magic está habilitada en la construcción de PropertyAccessor.

Sólo se requiere el uso de una de las estrategias anteriores.