【问题标题】:Use same entity field multiple times with different admin code in sonata form以奏鸣曲形式多次使用相同的实体字段和不同的管理代码
【发布时间】:2018-10-31 09:42:22
【问题描述】:

我在我的 Symfony 项目中使用 Sonata admin。我有 2 个实体,例如 ParentChild实体通过一对多关系连接到

我为具有不同 baseRoutName 的 child 实体创建了 2 个管理类。我需要在 Parent 实体奏鸣曲形式中使用 Child 实体字段 2 次。

//ParentAdmin.php
    $formMapper
            ->with('Child 1', ['class' => 'col-md-4'])
            ->add('child', CollectionType::class, [], [
                'edit' => 'inline',
                'inline' => 'table',
                'sortable' => 'position',
                'admin_code' => 'admin.child1'
            ])
            ->end()
            ->with('Child 2', ['class' => 'col-md-4'])
            ->add('child', CollectionType::class, [], [
                'edit' => 'inline',
                'inline' => 'table',
                'sortable' => 'position',
                'admin_code' => 'admin.child2'
            ])
            ->end();

这里的问题是我需要多次使用 child 字段。但是 Child 2 中的 child 字段会覆盖 Child 1 中的 child 字段。如您所见,我为这两个字段使用了不同的 admin_code。

我的预期输出是,

但我得到的实际输出是,

我知道这里的问题是重复的实体字段。是否可以多次显示同一字段?

有人有解决方案/建议吗?提前致谢!!

【问题讨论】:

    标签: php symfony one-to-many sonata-admin


    【解决方案1】:

    也许来晚了,但我也遇到了同样的问题,发现这个帖子没有答案,终于找到了解决方案,所以这里是为了将来的目的。

    我有一个带有生成文档的 Request 类,关注 get 和 add 函数:

    class Request
    {
        /**
         * @ORM\Id
         * @ORM\Column(type="integer")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        protected $id;
    
        /**
         * @ORM\OneToMany(targetEntity="GeneratedDocument", mappedBy="request", cascade={"all"}, orphanRemoval=true)
         */
        protected $generatedDocuments;
    
        /**
         * @var ArrayCollection
         * each of this attributes will get one type of $generatedDocuments
         */
        protected $generatedAttestationDocuments;
        protected $generatedCertificationDocuments;
    
        public function __construct()
        {
            $this->generatedDocuments = new ArrayCollection();
        }
    
        /**
         * Set the value of id.
         *
         * @param integer $id
         * @return \App\Entity\Request
         */
        public function setId($id)
        {
            $this->id = $id;
    
            return $this;
        }
    
        /**
         * Get the value of id.
         *
         * @return integer
         */
        public function getId()
        {
            return $this->id;
        }
    
        /**
         * @return Collection|GeneratedDocument[]
         */
        public function getGeneratedDocuments(): Collection
        {
            return $this->generatedDocuments;
        }
    
        public function addGeneratedDocument(GeneratedDocument $generatedDocument): self
        {
            if (!$this->generatedDocuments->contains($generatedDocument)) {
                $this->generatedDocuments[] = $generatedDocument;
                $generatedDocument->setRequest($this);
            }
    
            return $this;
        }
    
        public function removeGeneratedDocument(GeneratedDocument $generatedDocument): self
        {
            if ($this->generatedDocuments->contains($generatedDocument)) {
                $this->generatedDocuments->removeElement($generatedDocument);
                // set the owning side to null (unless already changed)
                if ($generatedDocument->getRequest() === $this) {
                    $generatedDocument->setRequest(null);
                }
            }
    
            return $this;
        }
    
        /**
         * @return Collection|GeneratedDocument[]
         *
         * @param int $type
         */
        protected function getTypedGeneratedDocuments(int $type): Collection
        {
            return $this->getGeneratedDocuments()->filter(function (GeneratedDocument $gd) use ($type) {
                if ($gd->getGeneratedDocumentModel()) {
                    return $type === $gd->getGeneratedDocumentModel()->getType();
                }
                return false;
            });
        }
    
        /**
         * @return Collection|GeneratedDocument[]
         */
        public function getGeneratedAttestationDocuments(): Collection
        {
            if (empty($this->generatedAttestationDocuments)) {
                $this->generatedAttestationDocuments =
                    $this->getTypedGeneratedDocuments(GeneratedDocumentModel::TYPE_ATTESTATION);
            }
    
            return $this->generatedAttestationDocuments;
        }
    
        public function addGeneratedAttestationDocument(GeneratedDocument $generatedDocument): self
        {
            $this->generatedAttestationDocuments[] = $generatedDocument;
            return $this->addGeneratedDocument($generatedDocument);
        }
    
        public function removeGeneratedAttestationDocument(GeneratedDocument $generatedDocument): self
        {
            return $this->removeGeneratedDocument($generatedDocument);
        }
    
        /**
         * @return Collection|GeneratedDocument[]
         */
        public function getGeneratedCertificationDocuments(): Collection
        {
            if (empty($this->generatedCertificationDocuments)) {
                $this->generatedCertificationDocuments =
                    $this->getTypedGeneratedDocuments(GeneratedDocumentModel::TYPE_CERTIFICATE);
            }
    
            return $this->generatedCertificationDocuments;
        }
    
        public function addGeneratedCertificationDocument(GeneratedDocument $generatedDocument): self
        {
            $this->generatedCertificationDocuments[] = $generatedDocument;
            return $this->addGeneratedDocument($generatedDocument);
        }
    
        public function removeGeneratedCertificationDocument(GeneratedDocument $generatedDocument): self
        {
            return $this->removeGeneratedDocument($generatedDocument);
        }
    }
    

    然后在 admin 中,您必须在每个 add 中给出不同的名称,这里我使用我键入的生成文档,所以没有重复问题,但它们没有映射,symfony 抱怨它。

    尝试使用'mapped' => false 没有解决任何问题,我发现最简单的方法是基于原始映射属性“generatedDocuments”的“虚拟映射”,只是在构建表单时愚弄 symfony 的时间。

    class RequestAdmin extends AbstractAdmin
    {
        protected function configureFormFields(FormMapper $formMapper): void
        {
            /** @var Request $createdRequest */
            $createdRequest = $this->getSubject();
    
            $metaData = $this->getModelManager()->getMetadata($this->getClass());
            //We need many CollectionType based on 'generatedDocuments', and we need an ArrayCollection for each of them
            //so here is a virtual mapping to make symfony accept the persistence of our CollectionType
            //then setter should fill 'generatedDocuments'
            $mapping = $metaData->getAssociationMappings()['generatedDocuments'];
            $mapping['fieldName'] = 'generatedAttestationDocuments';
            $metaData->mapOneToMany($mapping);
            $mapping['fieldName'] = 'generatedCertificationDocuments';
            $metaData->mapOneToMany($mapping);
    
            $formMapper
                ->with(('Attestation Deposit'))
                    ->add('generatedAttestationDocuments', CollectionType::class, [
                        'label' => false,
                        'by_reference' => false,
                        'btn_add' => 'Add Attestation',
                        'data' => $createdRequest->getGeneratedAttestationDocuments(),
                    ], [
                        'edit' => 'inline',
                        'inline' => 'table',
                        'admin_code' => 'admin.generated_document_attestation',
                    ])
                ->end()
                ->with(('Certificate'))
                    ->add('generatedCertificationDocuments', CollectionType::class, [
                        'label' => false,
                        'by_reference' => false,
                        'btn_add' => 'Add Certification',
                        'data' => $createdRequest->getGeneratedCertificationDocuments(),
                    ], [
                        'edit' => 'inline',
                        'inline' => 'table',
                        'admin_code' => 'admin.generated_document_certification',
                    ])
                ->end()
    
            //delete virtual mapping to avoid it to get handle like a real mapping
            unset($metaData->associationMappings['generatedAttestationDocuments']);
            unset($metaData->associationMappings['generatedCertificationDocuments']);
        }
    }
    

    我想知道一个最简单的方法,但它对我来说真的像个人 CollectionType 一样工作。

    希望对您有所帮助!

    【讨论】:

      猜你喜欢
      • 2017-04-13
      • 2018-04-19
      • 2018-03-21
      • 2015-02-24
      • 2019-08-11
      • 1970-01-01
      • 2016-06-12
      • 1970-01-01
      • 2015-07-22
      相关资源
      最近更新 更多