Используйте одно и то же поле сущности несколько раз с другим кодом администратора в форме сонаты - PullRequest
0 голосов
/ 31 октября 2018

Я использую администратор Sonata в моем проекте Symfony. У меня есть 2 сущности, такие как Родитель и Ребенок . Родительский объект связан с дочерним отношением один-ко-многим.

Я создал 2 административных класса для child сущности с другим baseRoutName. Мне нужно использовать дочерние поля сущностей в родительской форме сонаты сущностей 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 в Child 2 переопределяет поле child в Child 1 . Как видите, я использовал разные admin_code для этих 2 полей.

Мой ожидаемый результат:

enter image description here

Но фактический вывод, который я получаю,

enter image description here

Я знаю, что проблема здесь в дублировании полей сущностей. Можно ли отображать одно и то же поле несколько раз?

У кого-нибудь есть решение / предложение? Заранее спасибо !!

1 Ответ

0 голосов
/ 28 мая 2019

возможно, уже поздно, но у меня возникла та же проблема, я нашел этот пост без ответа и, наконец, нашел решение, так что вот оно для будущих целей.

У меня есть класс 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);
    }
}

Затем в админке вы должны давать разные имена в каждой надстройке, здесь я использую мои типизированные сгенерированные документы, чтобы не было проблем с дублированием, но они не отображаются, и Symfony жалуется на это.

Попытка использовать 'mapped' => false ничего не решала, самый простой способ, который я обнаружил, это «виртуальное отображение», основанное на исходном отображенном атрибуте generateDocuments, просто время, чтобы обмануть 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 для меня.

Надеюсь, это поможет!

...