未在EntityType字段中设置所选选项

时间:2019-08-19 09:03:56

标签: php symfony doctrine-orm

我有一个模块,可以在其中添加眼镜,在该模块中,我有一个类来添加这些眼镜的可用品牌。

我面临的问题是,当我去编辑一些眼镜时,品牌总是将占位符显示为选定选项,而不是上传时选择的品牌。

我看过类似的问题,但是似乎没有一个答案可以解决我的问题。

GlassesType.php

<?php

namespace Backend\Modules\Glasses\Domain\Glasses;

use Backend\Core\Language\Language;
use Backend\Form\EventListener\AddMetaSubscriber;
use Backend\Modules\Glasses\Domain\Brand\Brand;
use Backend\Modules\MediaLibrary\Domain\MediaGroup\MediaGroupType;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Backend\Core\Engine\TemplateModifiers;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Common\Form\ImageType;

final class GlassesType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {

        $builder->add(
            'brand',
            EntityType::class,
            [
                'class' => Brand::class,
                'label' => 'lbl.Brand',
                'choice_label' => 'name',
                'choice_value' => 'id',
                'placeholder' => 'Kies een merk...',
                'choice_translation_domain' => false,
                'query_builder' => function (EntityRepository $er) {
                    return $er->createQueryBuilder('i')
                        ->addOrderBy('i.name', 'ASC');
                },
            ]
        );
        dump($builder);
        $builder->add(
            'model',
            TextType::class
        );

+ ......

        $builder->addEventSubscriber(
            new AddMetaSubscriber(
                'Glasses',
                'GlassesDetail',
                GlassesRepository::class,
                'getUrl',
                [
                    'getData.getId',
                ],
                'model'
            )
        );
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults(['data_class' => GlassesDataTransferObject::class]);
    }

    private function getUploadMaxFileSize(): ?string
    {
        $uploadMaxFileSize = ini_get('upload_max_filesize');
        if ($uploadMaxFileSize === false) {
            return null;
        }

        // reformat if defined as an integer
        if (is_numeric($uploadMaxFileSize)) {
            return $uploadMaxFileSize / 1024 . 'MB';
        }

        // reformat if specified in kB
        if (mb_strtoupper(mb_substr($uploadMaxFileSize, -1)) === 'K') {
            return mb_substr($uploadMaxFileSize, 0, -1) . 'kB';
        }

        // reformat if specified in MB
        if (mb_strtoupper(mb_substr($uploadMaxFileSize, -1)) === 'M') {
            return $uploadMaxFileSize . 'B';
        }

        // reformat if specified in GB
        if (mb_strtoupper(mb_substr($uploadMaxFileSize, -1)) === 'G') {
            return $uploadMaxFileSize . 'B';
        }

        return $uploadMaxFileSize;
    }
}

Brand.php类

<?php

namespace Backend\Modules\Glasses\Domain\Brand;

use Backend\Modules\Glasses\Domain\Glasses\Glasses;
use DateTime;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table(name="GlassesBrand")
 * @ORM\Entity(repositoryClass="Backend\Modules\Glasses\Domain\Brand\BrandRepository")
 * @ORM\HasLifecycleCallbacks()
 */
class Brand
{
    /**
     * @var int
     *
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @var Glasses
     *
     * @ORM\OneToMany(targetEntity="Backend\Modules\Glasses\Domain\Glasses\Glasses", mappedBy="brand")
     */
    private $glasses;

    /**
     * @var string
     *
     * @ORM\Column(type="string")
     */
    private $name;

    /**
     * @var DateTime
     *
     * @ORM\Column(type="datetime")
     */
    private $createdOn;

    /**
     * @var DateTime
     *
     * @ORM\Column(type="datetime")
     */
    private $editedOn;

    public function __construct(
        string $name
    ) {
        $this->name = $name;

        $this->createdOn = new DateTime();
        $this->editedOn = new DateTime();
    }

    public function update(
        string $name
    ): void {
        $this->name = $name;

        $this->editedOn = new DateTime();
    }

    public function __toString(): string
    {
        return (string) $this->name;
    }

    public function getId(): int
    {
        return $this->id;
    }

    public function getGlasses(): Glasses
    {
        return $this->glasses;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function getCreatedOn(): DateTime
    {
        return $this->createdOn;
    }

    public function getEditedOn(): DateTime
    {
        return $this->editedOn;
    }
}

Glasses.php类

<?php

namespace Backend\Modules\Glasses\Domain\Glasses;

use Backend\Modules\MediaLibrary\Domain\MediaGroup\MediaGroup;
use Backend\Modules\Glasses\Domain\Brand\Brand;
use Common\Doctrine\Entity\Meta;
use DateTime;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table(name="Glasses")
 * @ORM\Entity(repositoryClass="Backend\Modules\Glasses\Domain\Glasses\GlassesRepository")
 * @ORM\HasLifecycleCallbacks()
 */
class Glasses
{
    /**
     * @var int
     *
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @var Meta
     *
     * @ORM\OneToOne(targetEntity="Common\Doctrine\Entity\Meta", cascade={"persist","remove"})
     */
    private $meta;

    /**
     * @var Brand
     *
     * @ORM\ManyToOne(targetEntity="Backend\Modules\Glasses\Domain\Brand\Brand", inversedBy="glasses")
     * @ORM\JoinColumn(name="brandId", referencedColumnName="id")
     */
    private $brand;

    /**
     * @var string
     *
     * @ORM\Column(type="string")
     */
    private $model;

    /**
     * @var string
     *
     * @ORM\Column(type="string")
     */
    private $description;

    /**
     * @var MainImage
     *
     * @ORM\Column(type="glasses_glasses_mainimage")
     */
    private $mainImage;

    /**
     * @var float
     *
     * @ORM\Column(type="decimal", scale=2)
     */
    private $price;

    /**
     * @var MediaGroup
     *
     * @ORM\OneToOne(
     *      targetEntity="Backend\Modules\MediaLibrary\Domain\MediaGroup\MediaGroup",
     *      cascade="persist",
     *      orphanRemoval=true
     * )
     * @ORM\JoinColumn(
     *      name="imageGalleryId",
     *      referencedColumnName="id",
     *      onDelete="cascade"
     * )
     */
    protected $imageGallery;

    /**
     * @var bool
     *
     * @ORM\Column(type="boolean")
     */
    private $sunglasses;

    /**
     * @var Sex
     *
     * @ORM\Column(type="glasses_glasses_sex", options={"default" = "none"})
     */
    private $sex;

    /**
     * @var bool
     *
     * @ORM\Column(type="boolean")
     */
    private $headerSpotlight;

    /**
     * @var bool
     *
     * @ORM\Column(type="boolean")
     */
    private $generalSpotlight;

    /**
     * @var int
     *
     * @ORM\Column(type="integer")
     */
    private $sequence;

    /**
     * @var DateTime
     *
     * @ORM\Column(type="datetime")
     */
    private $createdOn;

    /**
     * @var DateTime
     *
     * @ORM\Column(type="datetime")
     */
    private $editedOn;

    public function __construct(
        Meta $meta,
        Brand $brand,
        string $model,
        string $description,
        MainImage $mainImage,
        float $price,
        MediaGroup $imageGallery,
        bool $sunglasses,
        Sex $sex,
        bool $headerSpotlight,
        bool $generalSpotlight,
        bool $sequence
    ) {
        $this->meta = $meta;
        $this->brand = $brand;
        $this->model = $model;
        $this->description = $description;
        $this->mainImage = $mainImage;
        $this->price = $price;
        $this->imageGallery = $imageGallery;
        $this->sunglasses = $sunglasses;
        $this->sex = $sex;
        $this->headerSpotlight = $headerSpotlight;
        $this->generalSpotlight = $generalSpotlight;
        $this->sequence = $sequence;

        $this->createdOn = new DateTime();
        $this->editedOn = new DateTime();
    }

    public function update(
        Brand $brand,
        string $model,
        string $description,
        MainImage $mainImage,
        float $price,
        MediaGroup $imageGallery,
        bool $sunglasses,
        Sex $sex,
        bool $headerSpotlight,
        bool $generalSpotlight
    ): void {
        $this->brand = $brand;
        $this->model = $model;
        $this->description = $description;
        $this->mainImage = $mainImage;
        $this->price = $price;
        $this->imageGallery = $imageGallery;
        $this->sunglasses = $sunglasses;
        $this->sex = $sex;
        $this->headerSpotlight = $headerSpotlight;
        $this->generalSpotlight = $generalSpotlight;

        $this->editedOn = new DateTime();
    }

    public function __toString(): string
    {
        return $this->getModel();
    }

    public function getId(): int
    {
        return $this->id;
    }

    public function getMeta(): Meta
    {
        return $this->meta;
    }

    public function getBrand(): Brand
    {
        return $this->brand;
    }

    public function getModel(): string
    {
        return $this->model;
    }

    public function getText(): string
    {
        return $this->getModel();
    }

    public function getDescription(): string
    {
        return $this->description;
    }

    public function getMainImage(): MainImage
    {
        return $this->mainImage;
    }

    public function getMainImageWebPath(): string
    {
        return $this->mainImage->getWebPath();
    }

    public function getMainImageAbsolutePath(): string
    {
        return $this->mainImage->getAbsolutePath();
    }

    public function getPrice(): float
    {
        return $this->price;
    }

    public function getImageGallery(): MediaGroup
    {
        return $this->imageGallery;
    }

    public function isSunglasses(): bool
    {
        return $this->sunglasses;
    }

    public function getSex(): Sex
    {
        return $this->sex;
    }

    public function isHeaderSpotlight(): bool
    {
        return $this->headerSpotlight;
    }

    public function isGeneralSpotlight(): bool
    {
        return $this->generalSpotlight;
    }

    public function setSequence(int $sequence): void
    {
        $this->sequence = $sequence;
    }

    public function getSequence(): int
    {
        return $this->sequence;
    }

    public function getCreatedOn(): DateTime
    {
        return $this->createdOn;
    }

    public function getEditedOn(): DateTime
    {
        return $this->editedOn;
    }

    /**
     * @ORM\PreUpdate
     * @ORM\PrePersist
     */
    public function prepareToUploadMainImage(): void
    {
        $this->mainImage->prepareToUpload();
    }

    /**
     * @ORM\PostUpdate
     * @ORM\PostPersist
     */
    public function uploadMainImage(): void
    {
        $this->mainImage->upload();
    }

    /**
     * @ORM\PostRemove
     */
    public function removeMainImage(): void
    {
        $this->mainImage->remove();
    }
}

这为品牌<select>

提供了以下HTML
<select id="glasses_brand" name="glasses[brand]" required="required" class="form-control">
   <option value="" selected="selected">Kies een merk...</option>
   <option value="2">Gucci</option>
   <option value="1">Ray Ban</option>
   <option value="3">Tom Ford</option>
</select>

在这种情况下,应将“雷朋”作为选定的选项,而不是占位符。

formbuilder的转储返回以下内容:

FormBuilder {#1274 ▼
  -children: array:1 [▶]
  -unresolvedChildren: array:1 [▶]
  #locked: false
  -dispatcher: EventDispatcher {#1275 ▶}
  -name: "glasses"
  -propertyPath: null
  -mapped: true
  -byReference: true
  -inheritData: false
  -compound: true
  -type: ResolvedTypeDataCollectorProxy {#1266 ▶}
  -viewTransformers: []
  -modelTransformers: []
  -dataMapper: PropertyPathMapper {#1276 ▶}
  -required: true
  -disabled: false
  -errorBubbling: true
  -emptyData: Closure {#1231 ▶}
  -attributes: array:1 [▶]
  -data: UpdateGlasses {#1268 ▼
    -glasses: Glasses {#1127 ▶}
    +meta: Meta {#1042 ▶ …2}
    +brand: null    <-- SHOULD CONTAIN SELECTED BRAND
    +model: "Aviator"
    +description: "Test"
    +mainImage: MainImage {#1164 ▶}
    +price: 150.0
    +imageGallery: MediaGroup {#1156 ▶ …2}
    +sunglasses: false
    +sex: Sex {#1163 ▶}
    +headerSpotlight: false
    +generalSpotlight: false
    +"title": Brand {#1170 ▶ …2}
  }
  -dataClass: "Backend\Modules\Glasses\Domain\Glasses\GlassesDataTransferObject"
  -dataLocked: true
  -formFactory: FormFactory {#1076 ▶}
  -action: ""
  -method: "POST"
  -requestHandler: HttpFoundationRequestHandler {#1189 ▶}
  -autoInitialize: true
  -options: array:35 [▶]
}

在这里我可以看到品牌是null,这很可能会引起问题。

1 个答案:

答案 0 :(得分:-1)

这是一个对我有用的简单示例。希望对您有帮助

控制器:

    /**
     * @Route("/glasses/{glasses}/edit", methods={"GET", "PUT"}, requirements={"glasses"="\d+"})
     */
    public function update(Request $request, Glasses $glasses)
    {
        $form = $this->formFactory->create(GlassesType::class, $glasses, []);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            return new Response(':)');
        }

        return $this->render('base.html.twig', [
            'form' => $form->createView(),
        ]);
    }

品牌实体:

class Brand
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $name;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Glasses", mappedBy="brand")
     */
    private $glasses;

    public function __construct()
    {
        $this->glasses = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    /**
     * @return Collection|Glasses[]
     */
    public function getGlasses(): Collection
    {
        return $this->glasses;
    }

    public function addGlasses(Glasses $glass): self
    {
        if (!$this->glasses->contains($glass)) {
            $this->glasses[] = $glass;
            $glass->setName($this);
        }

        return $this;
    }
}

眼镜实体:

class Glasses
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $name;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Brand", inversedBy="glasses")
     * @ORM\JoinColumn(name="brand_id", referencedColumnName="id")
     */
    private $brand;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function setName(?string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getBrand(): ?Brand
    {
        return $this->brand;
    }

    public function setBrand(?Brand $brand): self
    {
        $this->brand = $brand;

        return $this;
    }
}

和表单类型:

class GlassesType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('id', HiddenType::class)
            ->add('name', TextType::class)
            ->add('brand', EntityType::class, [
                'class' => Brand::class,
                'choice_label' => 'name',
                'query_builder' => function (EntityRepository $er) {
                    return $er->createQueryBuilder('i')
                        ->addOrderBy('i.name', 'ASC');
                },
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Glasses::class,
        ));
    }
}