簡體   English   中英

對於某些,但不是全部,表單提交得到“無法確定屬性的訪問類型”id“。”

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

我有一個復雜的形式映射到集合Entity ,允許在一個給定的價格購買機票的事件,對於大多數它工作的事件,但他們中的一個,我們可重復的方式得到的錯誤Could not determine access type for property "id"

在這種情況下,我知道Could not determine access type for property X是因為缺少setter。 確實沒有setId()方法並且id protected ,但我認為symfony不應該首先嘗試設置id(因為它適用於其他表單,即票據被購買,並且正確顯示鏈接到事件等) 。)

所以我的問題是為什么在某些情況下symfony需要setId()

我有以下實體

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

事實上,“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;
    }
}

和表格

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

創建表單的控制器如下所示

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

異常回溯如下

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')

在添加一些debug我可以看到2個Pricing

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

所以似乎symfony試圖通過其他有效/現有的定價覆蓋此定價的ID(這是有效的/現有的),這就是我認為它試圖通過嘗試調用來“替換”它的原因設定者並失敗,但為什么會這樣做?

編輯:

經過一些調試后,我發現了一個令人不安的巧合:

  • d82cafb8-432b-4e20-ac9f-66e48dc55458是我在addQuantitiesByPricing方法中添加一些調試時添加的第一個id
  • 80424145-ca68-4dce-b4f0-644a423d3aad是提交表單中索引為0的定價ID

Edit2:我的控制器創建表單的方式(以及調用addQuantitiesByPricing使d82cafb8-432b-4e20-ac9f-66e48dc55458首先出現),使得我們首先從數據庫中檢索這些ID,然后再獲取Ids POSTed

問題是在創建表單的主要實體(即OrderFront )時使用addQuantitiesByPricing添加元素的順序與它們在HTML中添加它們的位置不同(在OrderFront文件中隱藏了一個sort

因此, QuantityByPricing的POSTed數組與數據庫創建的QuantityByPricing數組的順序不同,所以當Symfony正在尋找需要更新哪個字段的魔法時,它看到我的數組的第一個元素有不同的id比POSTed數組的第一個元素,然后嘗試通過首先搜索它的setter來替換它,所以setId()因此異常

之前我沒有看到這個bug的原因是因為一些(非)幸運的原因來自數據庫的數組已經排序,所以樹枝排序什么也沒做

注意:不直接與此特定上下文相關,但如果發布數組的大小小於數據庫數組的大小,則將獲得相同的堆棧跟蹤(除了最后一個參數將為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)

注意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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM