带有检查是否已存在的Symfony表单类型(LocationType)(尝试过EventListener,Transformer。...)

时间:2019-07-16 22:05:31

标签: php symfony symfony4 symfony-forms

我的愿望

我想为Location实体提供一个独立的表单类型,可以将其添加到所需的任何位置。如果为null,则应为null,而不是空的Location

当前问题

我的问题是,当我提交null时,将使用先前设置的位置,或者当我解决此问题时,该位置重复且不是唯一。

基本代码

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 [...]
}

我的尝试

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());

它工作得很好-但是当我要将其设置为null时不是,因为那样的话它将被忽略,并且将使用过去的位置。

示例{}

{}

确定,因为尚未提交location,因此将其忽略。 $clearMissing = false-> $form->submit($request->request->all(), false);

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

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

确定,因为未找到lat / log 时创建新实体,并在lat / lng 找到

示例{"location": null}

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

错误,我希望这里的位置为null,而不是父位置。

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;
    }
}

它也可以正常工作,但即使设置为空也存在问题。

示例{}

{}

确定,因为尚未提交location,因此将其忽略。 $clearMissing = false-> $form->submit($request->request->all(), false);

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

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

确定,因为未找到lat / log 时创建新实体,并在lat / lng 找到

示例{"location": null}

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

错误,我希望这里的位置为null,而不是父位置。

Doctrine prePersist侦听器

这里的问题是,它不被要求进行更新,而且效果也不佳,因为它超出了类型范围。

更新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);
    });

我现在更改了事件监听器,以使其在PRE_SUBMIT上监听并添加了选项required,该选项设置为false

但是提交有效内容时出现错误。

请求:

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

响应:

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

:(

0 个答案:

没有答案