嵌入表单集合错误:无法确定属性的访问类型

时间:2017-02-15 10:26:47

标签: doctrine-orm symfony symfony-forms

根据this tutorial,我正在尝试将Service表单的集合嵌入到Tag表单中。 ServiceTag个实体具有多对多关系。

表单正确呈现。但是当我提交表格时,我得到了

  

无法确定属性“tagList”的访问类型

错误。我不明白为什么新的Service对象没有通过调用addTag()方法添加到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 ))); } 类。

的ServiceType

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

服务类

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

标记类

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

的ServiceController

String ast_a = "";
        String ast_b = "";
        String ast_c = "";
        String ast_d = "";
        String ast_e = "";
        int a = Integer.parseInt(request.getParameter("strong-dissatisfy"));
        int b = Integer.parseInt(request.getParameter("dissatisfy"));        
        int c = Integer.parseInt(request.getParameter("neutral"));
        int d = Integer.parseInt(request.getParameter("satisfy"));
        int e = Integer.parseInt(request.getParameter("strong-satisfy"));

8 个答案:

答案 0 :(得分:4)

您能否尝试通过此网址实施代码?

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#owning-and-inverse-side-on-a-manytomany-association

首先,请尝试更改映射/反面,并从$service->addTag($this);方法中删除Tag::addService

答案 1 :(得分:2)

也许问题是Symfony无法访问该属性?

如果你看一下抛出异常的位置(PropertyAccessor类中的writeProperty方法),它会说它可以被抛出:

  

如果财产不存在或不公开。

在你提到的教程中,它有属性$ tags和方法addTag。我只是在这里猜测,但也许会有一个惯例,它试图调用一个方法名add($singularForm),这对你来说是失败的,因为属性是tagList而方法是{ {1}}。

我不是100%肯定,但您可以通过在Symfony方法中设置一个停止点来尝试调试,以了解它被抛出的原因。

答案 2 :(得分:2)

简短版:

我遇到了这个问题并通过为受影响的属性添加一个setter来解决它:

  

无法确定属性“tagList”的访问类型

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

长版:

错误消息表明Symfony正在尝试修改对象的状态,但由于其类的设置方式无法弄清楚如何实际进行更改。

Taking a look at Symfony's internals,我们可以看到Symfony为您提供了5次机会,可以从上到下按顺序选择最佳的:

  1. 一个名为setProperty()的setter方法,带有一个参数:
  2. 这是Symfony检查的第一件事,也是实现这一目标的最明确的方法。据我所知,这是最好的做法:

    class Entity {
    
        protected $tagList;
    
        //...
    
        public function getTagList()
        {
            return $this->tagList;
        }
    
        //...
    }
    
    1. 在一个方法中使用一个参数组合getter和setter:
    2. 重要的是要意识到Symfony也会访问此方法,以便获取对象的状态。由于这些方法调用不包含参数,因此此方法中的参数必须是可选的。

      class Entity {
      
          protected $tagList;
      
          //...
      
          public function tagList($tags = null)
          {
              if($reps){
                  $this->tagList = $tags;
              } else {
                  return $this->tagList;
              }
          }
      
          //...
      }
      
      1. 受影响的财产被宣布为公共:

        class Entity {
        
            public $tagList;
            //... other properties here
        }
        
      2. __set魔法:

      3. 这将影响所有属性,而不仅仅是您想要的属性。

        class Entity {
        
            public $tagList;
        
            //...
        
            public function __set($name, $value){
                $this->$name = $value;
            }
            //...
        }
        
        1. __call魔法(在某些情况下):
        2. 我无法确认这一点,但内部代码建议在PropertyAccessor构建时启用magic时可以这样做。

          只需使用上述策略之一。

答案 3 :(得分:1)

也许您忘记了__construct() Service类和Tag类来初始化$ tagList和$ serviceList?

$this->tagList = new ArrayCollection();

$this->serviceList = new ArrayCollection();

答案 4 :(得分:1)

这似乎是构造函数的错误。试试这个:

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

答案 5 :(得分:1)

这是一个很长的镜头,但看着你的注释,我认为问题可能与你的manyToMany关系有关。尝试更改拥有方和反方(交换关系),除非您特别需要从两端更新(在这种情况下,我认为唯一的解决方案是手动添加对象或使用oneToMany关系)。

  

忽略仅对关联的反面进行的更改。   确保更新双向关联的两侧(或在   至少是拥有方,从学说的角度来看)

这是一个与我以前遇到过的学说相关的问题,请参阅: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/unitofwork-associations.html

答案 6 :(得分:0)

基于Symfony 3.3.10

我实际上遇到过很多次这个问题,最后一旦我发现这个问题来自哪里,根据您给实体属性的名称,可能会发生加法器和<您的收藏属性的strong> remover 并不完全符合您的预期。

示例:您的实体属性名称为“foo”,您可能希望将加法器称为“addFoo”并将其移除“removeFoo”,但突然之后“无法确定属性的访问类型” 出现。

因此,您开始担心在代码中搜索w / e问题,而只需在Symfony核心文件中查看此文件:

<强>供应商/ symfony的/ symfony的/ SRC / Symfony的/组件/ PropertyAccess / PropertyAccessor.php

在此文件中,有一个名为 findAdderAndRemover 的方法。 使用您的调试器去那里,您最终会发现symfony会为您的加法器/移除器搜索奇怪的名称,它们实际上可能以“um”或“on”或“us”结尾,具体取决于语言(人类语言)你曾经用它们命名。因为我是意大利人,所以这种情况经常发生。

注意这一点,因为修复可能就像更改实体中用于添加/删除方法的名称一样简单,以使它们与Symfony核心所寻找的匹配。

当我使用 bin / console doctrine:generate:entities 为我自动创建方法时,这种情况发生在我身上

答案 7 :(得分:0)

如果您正在使用symfony,并使用EntityRepository而不是CollectionType,请确保在表单构建中使用df['month']=df.month ,否则输入将针对一个实体而不是多个实体,因此它将调用{ {1}}而不是使用方法'multiple' => true,setTagList