简体   繁体   English

对于某些,但不是全部,表单提交得到“无法确定属性的访问类型”id“。”

[英]for some, but not all, form submission got “Could not determine access type for property ”id“.”

I have a complex form that maps to a collection of Entity , that permits to buy ticket at a given pricing for an event, for most of the events it works, but for one of them, we got in a repeatable fashion the error Could not determine access type for property "id" 我有一个复杂的形式映射到集合Entity ,允许在一个给定的价格购买机票的事件,对于大多数它工作的事件,但他们中的一个,我们可重复的方式得到的错误Could not determine access type for property "id"

In such a case I know that Could not determine access type for property X is because a setter is missing. 在这种情况下,我知道Could not determine access type for property X是因为缺少setter。 There's indeed no setId() method and id is protected , but I think symfony should not try to set the id in the first place (because it works for the other forms, ie the tickets are bought, and appears correctly link to the event etc.) 确实没有setId()方法并且id protected ,但我认为symfony不应该首先尝试设置id(因为它适用于其他表单,即票据被购买,并且正确显示链接到事件等) 。)

So my question is why in some case symfony REQUIRES the setId() 所以我的问题是为什么在某些情况下symfony需要setId()

I have the following entities 我有以下实体

class OrderFront
{
    use Traits\HasId;
    /**
     * List of pricings set on this event
     *
     * @Assert\Valid()
     * @ORM\OneToMany(  
     *     targetEntity="QuantityByPricing",
     *     mappedBy="orderFront",
     *     cascade={"persist", "remove"}
     * )
     */
    private $quantitiesByPricing;

    /**
     * @Assert\NotBlank()
     * @Assert\NotNull()
     */
    public $occurenceId;

    public function getQuantitiesByPricing(): Collection
    {
        return $this->quantitiesByPricing;
    }

    public function addQuantitiesByPricing(QuantityByPricing $quantityByPricing)
    {
        $quantityByPricing->setOrderFront($this);
        $this->quantitiesByPricing[] = $quantityByPricing;
        return $this;
    }

}

class QuantityByPricing
{
    use Traits\HasId;

    /**
     * @var int
     * @ORM\Column(type="integer")
     */
    public $quantity = 0;

    /**
     * The pricing of this ticket
     *
     * @var Pricing
     *
     * @ORM\ManyToOne(targetEntity="Pricing")
     * @ORM\JoinColumn(
     *     name="pricing_id",
     *     nullable=false,
     *     referencedColumnName="id"
     * )
     */
    public $pricing;
}

Indeed the trait "HasId" has no setter (but it's on purpose) or at least until now it has never been a problem 事实上,“HasId”这个特质没有任何特效(但它是故意的)或至少到现在为止从未出现过问题

trait HasId
{
    /** 
     *
     * @ORM\GeneratedValue(strategy="UUID")
     * @ORM\Column(name="id", type="guid") }
     * @ORM\Id
     *
     * @Assert\Uuid()
     */
    private $id;

    /**
     * Get id
     *
     * @return guid
     */
    public function getId()
    {
        return $this->id;
    }
}

And the forms 和表格

    class OrderType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {   
            $builder
                ->add(
                    'quantitiesByPricing',
                    CollectionType::class,
                    ['entry_type' => QuantityByPricingType::class]
                )
                ->add('occurenceId', HiddenType::class)
           ;
        }
        public function configureOptions(OptionsResolver $resolver)
        {   
            $resolver->setDefaults(['data_class' => 'AppBundle\Entity\OrderFront']);
        }
    }

    /**
     * sub-form to buy X tickets of a given pricing
     */
    class QuantityByPricingType extends AbstractType
    {   
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('quantity')
                ->add('pricing',HiddenPricingType::class)
            ;
        }

        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults(['data_class' => 'AppBundle\Entity\QuantityByPricing']);
        }
    }

    /**
     *
     */
    class HiddenPricingType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {   
            $builder->add('id', HiddenType::class);
        }

        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults(['data_class' => 'AppBundle\Entity\Pricing']);
        }
    }

class Pricing
{
    use Traits\HasId;
}

The controller creating the form looks like this 创建表单的控制器如下所示

      // call the DB to set the possible pricings
      // inside it calls addQuantityByPricing
      $orderFront = $this->_createOrderFront(); 
      $form = $this->createForm(OrderType::class, $orderFront);
      $form->handleRequest($request);

The exception traceback is the following 异常回溯如下

Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException:
Could not determine access type for property "id".

  at vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php:652
  at Symfony\Component\PropertyAccess\PropertyAccessor->writeProperty(array(object(Pricing), object(Pricing)), 'id', '80424145-ca68-4dce-b4f0-644a423d3aad')

And when adding some debug I can see that the 2 Pricing are 在添加一些debug我可以看到2个Pricing

array:2 [▼
  0 => Pricing {#1375 ▶}   # id  "d82cafb8-432b-4e20-ac9f-66e48dc55458"
  1 => & Pricing {#1375 ▶} # id  "d82cafb8-432b-4e20-ac9f-66e48dc55458"
]

So it seems that symfony is trying to override the id of this pricing (which is a valid/existing one) by an other valid/existing one, which is I think the reason why it try to "replace" it, by trying to call the setter and fails, but why does it do so ? 所以似乎symfony试图通过其他有效/现有的定价覆盖此定价的ID(这是有效的/现有的),这就是我认为它试图通过尝试调用来“替换”它的原因设定者并失败,但为什么会这样做?

Edit: 编辑:

After some more debugging I found a troubling coincidence: 经过一些调试后,我发现了一个令人不安的巧合:

  • d82cafb8-432b-4e20-ac9f-66e48dc55458 is the first id to add when i added some debug in the addQuantitiesByPricing method d82cafb8-432b-4e20-ac9f-66e48dc55458是我在addQuantitiesByPricing方法中添加一些调试时添加的第一个id
  • 80424145-ca68-4dce-b4f0-644a423d3aad is the pricing id with the index 0 in the submitted form 80424145-ca68-4dce-b4f0-644a423d3aad是提交表单中索引为0的定价ID

Edit2: the way my controller create the form (and which is the one calling the addQuantitiesByPricing making d82cafb8-432b-4e20-ac9f-66e48dc55458 to appear first ), make that we first retrieve these Ids from the database BEFORE taking the Ids POSTed Edit2:我的控制器创建表单的方式(以及调用addQuantitiesByPricing使d82cafb8-432b-4e20-ac9f-66e48dc55458首先出现),使得我们首先从数据库中检索这些ID,然后再获取Ids POSTed

The problem was that the order in which the elements were added using addQuantitiesByPricing when creating the main entity of the form (ie OrderFront ) was not the same in which they were added in the HTML (there was a sort hidden in the twig file ) 问题是在创建表单的主要实体(即OrderFront )时使用addQuantitiesByPricing添加元素的顺序与它们在HTML中添加它们的位置不同(在OrderFront文件中隐藏了一个sort

So the POSTed array of QuantityByPricing was not in the same order as the array of QuantityByPricing created by the database, so when Symfony was doing its magic to see which field needed to be updated, it saw that the first element of my array had a different id than the first element of the POSTed array, and then tried to replace it by searching first its setter so setId() hence the exception 因此, QuantityByPricing的POSTed数组与数据库创建的QuantityByPricing数组的顺序不同,所以当Symfony正在寻找需要更新哪个字段的魔法时,它看到我的数组的第一个元素有不同的id比POSTed数组的第一个元素,然后尝试通过首先搜索它的setter来替换它,所以setId()因此异常

The reason why I didn't see this bug before was because for some (un)lucky reason the array coming from the database was already sorted, so the twig sort was doing nothing 之前我没有看到这个bug的原因是因为一些(非)幸运的原因来自数据库的数组已经排序,所以树枝排序什么也没做

Note: not related directly to this specific context, but if the size of the posted array is less than the size of the database array you will get the same stacktrace (except the last argument will be null ) 注意:不直接与此特定上下文相关,但如果发布数组的大小小于数据库数组的大小,则将获得相同的堆栈跟踪(除了最后一个参数将为null

Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException:
Could not determine access type for property "id".

  at vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php:652
  at Symfony\Component\PropertyAccess\PropertyAccessor->writeProperty(array(object(Pricing), object(Pricing)), 'id', null)

note2: an other solution that could had work would have been to reorder the array before submiting it using the PRE_SUBMIT event in my OrderType 注意2:另一个可能有效的解决方案是在使用我的OrderTypePRE_SUBMIT事件提交数组之前重新排序数组

        ->addEventListener(
            FormEvents::PRE_SUBMIT,
            function (FormEvent $event) {
                $submittedData = $event->getData();
                if (!array_key_exists('quantitiesByPricing', $submittedData)) {
                    return;
                }
                $form = $event->getForm();
                dump($submittedData['quantitiesByPricing']);

                //Re-index the array to ensure the forms
                // stay in the submitted order.
                $submittedData['quantitiesByPricing'] = /* some code to reorder the submitted form in the same order as the data from the database */

                $event->setData($submittedData);
            }
        )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Symfony - 无法确定属性“id”的访问类型 - Symfony - Could not determine access type for property “id” 无法确定访问类型 - Could not determine access type 在类“ App \\ Entity \\ GameGenre”中无法确定属性“游戏”的访问类型: - Could not determine access type for property “games” in class “App\Entity\GameGenre”: Symfony 4 | ManyToMany关系-无法确定属性的访问类型 - Symfony 4 | ManyToMany Relation - Could not determine access type for property 使用EntityType表单构建器时,Symfony无法确定访问类型 - Symfony Could not determine access type when using EntityType form builder 将'by reference'设置为false,在symfony表单上抛出'无法确定访问类型' - setting 'by reference' to false, on symfony form throws 'Could not determine access type' 无法确定 class “App\Entity\XXXX”中属性“image”的访问类型。 Symfony 4 - EasyAdmin 3.2 - VichUploader - Could not determine access type for property “image” in class “App\Entity\XXXX”. Symfony 4 - EasyAdmin 3.2 - VichUploader 如何在表单提交中包含ID? - How to include the id in the submission of the form? 确定提交表单后是否选中了一个复选框 - Determine whether a checkbox is checked upon form submission 提交表单时禁止访问403 - Access Forbidden on Form Submission 403
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM