douna4762 2019-07-16 22:05
浏览 54

具有检查的Symfony表单类型(如果已存在)(LocationType)(Tried EventListener,Transformer ....)

My wish

I want a independent form type for my Location entity which I can add everywhere I want. When it's null then it should be null and not an empty Location.

Current problem

My problem is either that when I submit null then the previous set location will be used or when I fixed this issue its that the location is duplicated and not unique.

Base code

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults([
        'data_class' => Location::class,
        'by_reference' => false
    ]);
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('place_id', null, ['property_path' => 'placeId'])
        ->add('latitude')
        ->add('longitude')
        ->add('description')
    ;
    // [...] See below examples [...]
}

My tries

EventListener

$builder->addEventListener(FormEvents::SUBMIT, function (FormEvent $event)
    {
//      $event->setData($this->locationRepository->find(19));
//      $event->getForm()->setData($this->locationRepository->find(17));
//      /** @var Location $value */
        $value = $event->getData();
//      var_dump(1, $value, $event->getForm()->getData()->getId());
        $location = null;
        if ($value)
        {
            $location = $this->locationRepository->findOneBy(['latitude' => $value->getLatitude(), 'longitude' => $value->getLongitude()]);
//          var_dump('Location found', $location->getId());
            if(!$location)
            {
                var_dump('-------------------- NEW LOCATION ----------------------------');
                $location = new Location();
                $location->setLongitude($value->getLongitude());
                $location->setLatitude($value->getLatitude());
                $location->setDescription($value->getDescription());
                $location->setPlaceId($value->getPlaceId());
            }
//          $event->setData($location);
//          $event->getForm()->setData($location);
        }
        $event->setData($location);
//      var_dump($location->getId());

It's working perfect - but not when I want to set it to null, because then it's ignored and the past location will be used.

Example {}

{}

OK because the location was not submitted so it's ignored. $clearMissing = false -> $form->submit($request->request->all(), false);

Example {"location": {"latitude": 12.0, "longitude": 99.0}}

{"location": {
    "latitude": 12.0,
    "longitude": 99.0
}}

OK because its creating new entity when lat/log isn't found and it reuses the existing entity when lat/lng is found.

Example {"location": null}

{"location": {
    "latitude": 12.0,
    "longitude": 99.0
}}

Wrong, here I expect that the location is null and not the parent one.

ModelTransformer

class UniqueLocationTransformer implements DataTransformerInterface
{
    private $locationRepository;

    public function __construct(LocationRepository $locationRepository)
    {
        $this->locationRepository = $locationRepository;
    }

    public function transform($value)
    {
        return $value;
    }

    public function reverseTransform($value)
    {
        if ($value)
        {
            $location = $this->locationRepository->findOneBy(['latitude' => $value->getLatitude(), 'longitude' => $value->getLongitude()]);
            if($location)
            {
                return $location;
            }
            $location = new Location();
            $location->setLongitude($value->getLongitude());
            $location->setLatitude($value->getLatitude());
            $location->setDescription($value->getDescription());
            $location->setPlaceId($value->getPlaceId());
        }
        return $value;
    }
}

It's working fine, too but even the problem with setting null.

Example {}

{}

OK because the location was not submitted so it's ignored. $clearMissing = false -> $form->submit($request->request->all(), false);

Example {"location": {"latitude": 12.0, "longitude": 99.0}}

{"location": {
    "latitude": 12.0,
    "longitude": 99.0
}}

OK because its creating new entity when lat/log isn't found and it reuses the existing entity when lat/lng is found.

Example {"location": null}

{"location": {
    "latitude": 12.0,
    "longitude": 99.0
}}

Wrong, here I expect that the location is null and not the parent one.

Doctrine prePersist listener

Here the problem is that it's not called for updates and it's not so good because its out of the type scope.

Update 17.7. 18:03 (gmt+2)

$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event)
    {
        $value = $event->getData();
        $location = null;
        if (is_array($value) && array_key_exists('latitude', $value))
        {
            $location = $this->locationRepository->findOneBy(['latitude' => $value['latitude'], 'longitude' => @$value['longitude'] || 0]);
            if(!$location)
            {
                $location = new Location();
                $location->setLongitude(array_key_exists('longitude', $value) ? $value['longitude'] : null);
                $location->setLatitude(array_key_exists('latitude', $value) ? $value['latitude'] : null);
                $location->setDescription(array_key_exists('description', $value) ? $value['description'] : null);
                $location->setPlaceId(array_key_exists('place_id', $value) ? $value['place_id'] : null);
            }
        }
        var_dump($location);
        $event->setData($location);
    });

I changed the event listener now so that its listening on PRE_SUBMIT and added option required which is set to false.

But then I'm getting an error when submitting something valid.

Request:

{"location": {"latitude": 13, "longitude": 14}}

Response:

{
  "location": [
    "This value is not valid."
  ]
}

:(

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 微信会员卡接入微信支付商户号收款
    • ¥15 如何获取烟草零售终端数据
    • ¥15 数学建模招标中位数问题
    • ¥15 phython路径名过长报错 不知道什么问题
    • ¥15 深度学习中模型转换该怎么实现
    • ¥15 HLs设计手写数字识别程序编译通不过
    • ¥15 Stata外部命令安装问题求帮助!
    • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
    • ¥15 TYPCE母转母,插入认方向
    • ¥15 如何用python向钉钉机器人发送可以放大的图片?