我有一个模块,可以在其中添加眼镜,在该模块中,我有一个类来添加这些眼镜的可用品牌。
我面临的问题是,当我去编辑一些眼镜时,品牌总是将占位符显示为选定选项,而不是上传时选择的品牌。
我看过类似的问题,但是似乎没有一个答案可以解决我的问题。
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>
<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
,这很可能会引起问题。
答案 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,
));
}
}