将一组表单输入转换为JSON

时间:2019-04-03 17:50:26

标签: json symfony frameworks symfony4

这听起来有点复杂,因为我对JSON完全陌生,但是请允许我,我真的很需要这个。 让我开始展示我的实体

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\TypeParkingRepository")
 */
class TypeParking
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

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


    /**
     * @ORM\Column(type="date", nullable=true)
     */
    private $jourdebut;

    /**
     * @ORM\Column(type="date", nullable=true)
     */
    private $jourfin;


    /**
     * @ORM\Column(type="json_array", nullable=true)
     */
    private $exception;


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



    public function getJourdebut(): ?\DateTimeInterface
    {
        return $this->jourdebut;
    }

    public function setJourdebut(\DateTimeInterface $jourdebut): self
    {
        $this->jourdebut = $jourdebut;

        return $this;
    }

    public function getJourfin(): ?\DateTimeInterface
    {
        return $this->jourfin;
    }

    public function setJourfin(\DateTimeInterface $jourfin): self
    {
        $this->jourfin = $jourfin;

        return $this;
    }


    public function getException() {
        return array_merge([
            'name' => null,
            'datedebut' => null, 
            'datefin' => null, 
            'heuredebut' => null, 
            'heurefin' => null, 

            // other sub-fields "empty" values
        ], $this->exception ?? [] // prevent array_merge from failing if exception is empty
        );
    }

    public function setException($exception): self
    {
        $this->exception = $exception;

        return $this;
    }

    public function getLibelle(): ?string
    {
        return $this->libelle;
    }

    public function setLibelle(string $libelle): self
    {
        $this->libelle = $libelle;

        return $this;
    }
}

您可以看到我有一个称为异常的属性,现在该属性具有许多子属性,例如名称,datedebut,datefin ... 因此,我必须使用JSON格式。 所以我创建了一个名为TypeParkingType.php的表单类型。

<?php

namespace App\Form;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\TimeType;
use Symfony\Component\Form\Extension\Core\Type\DateType;

use App\Entity\TypeParking;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class TypeParkingType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('libelle')
            ->add('tempsmax')
            ->add('jourdebut')
            ->add('jourfin')

            ->add('jourstravail_jour', TextType::class, ['property_path' => 'jourstravail[jour]'])
            ->add('jourstravail_debut', TextType::class, ['property_path' => 'jourstravail[debut]'])
            ->add('jourstravail_fin', TextType::class, ['property_path' => 'jourstravail[fin]'])


            ->add('Exception_Name', TextType::class, ['property_path' => 'exception[name]'])
            ->add('Starting_date', DateTimeType::class, [
                'property_path' => 'exception[datedebut]',
            ])
            ->add('Ending_date', DateTimeType::class, [
                'property_path' => 'exception[datefin]',
            ])
            ->add('Starting_time', TextType::class, ['property_path' => 'exception[heuredebut]'])
            ->add('Ending_time', TextType::class, ['property_path' => 'exception[heurefin]'])

        ;
    }

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


可悲的是,这是行不通的,因为即使将数据插入数据库后,它仍会以一种无法读取的不切实际的方式进行操作。 为了使其更加复杂,每种形式都可以具有多个异常,这意味着我必须以如下方式解析数据:例如:{exceptionName(datedebut:...,datefin ...,time:...), exceptionname2 ....}

我的意思是不可能做到的是,它给了我一个像这样的字符串https://imgur.com/a/ydYbpaQ,它是:

  1. 当我进入所选类型的编辑页面时,出现此错误: Unable to transform value for property path "exception[datedebut]": Expected a \DateTimeInterface.

  2. 我无法从中一一提取数据

TL; DR:如何将与异常相关的值插入数据库中的单个JSON字符串中。

1 个答案:

答案 0 :(得分:0)

我的建议是添加一个新的ExceptionType,将异常字段移至其中(给定data_class中的null(本质上是一个数组)。

以您的主要形式:

->add('exception', CollectionType::class, [
     'entry_type' => ExceptionType::class,
     // have a look at the other options!
   ]); 

(有关CollectionType的信息,请参见https://symfony.com/doc/current/reference/forms/types/collection.html

对于您的序列化和反序列化问题(本质上就是这样),我建议您使用数据转换器,将其应用于日期字段。

它实际上需要一个日期字符串'2019-01-02'或任何东西,并将其转换为DateTime,反之亦然。这样,您的表单提供的DateTime不会序列化为某个对象,而是一个字符串。

请参阅https://symfony.com/doc/current/form/data_transformers.html

您的CallbackTransformer类似于:

        new CallbackTransformer(
            function (string $string=null) {
                // transform string to DateTime
                return $string ? new \DateTime($string) : null;
            },
            function (\DateTime $datetime=null) {
                // transform the string back to an array
                return $datetime ? $datetime->format('Y-m-d') : null
            }
        )

为了使它对于您现有的数据库条目而言正常工作,必须删除它们或手动修复,以便日期字符串仅为YYYY-MM-DD而不是{ ... },并且必须包装异常,以便远在[[...]'中,因此它是一个数组。

更新

当然,由于对异常的更改(现在包含多个异常,而不是一个),您必须更改Entity的getException方法:

public function getException() {
    return $this->exception ?? [];
}

可能您可以删除整个方法...我不确定tbh。