【问题标题】:Transform form field value in Symfony在 Symfony 中转换表单字段值
【发布时间】:2017-08-01 16:44:17
【问题描述】:

我正在使用表列以 Unix 时间戳格式(基本上是长度为 11 的整数)存储“date_of_creation”(或 created_at)。

同时,我想在我的创建/编辑网络表单(Bootstrap Datepicker)中使用 DateTime 格式“d-m-Y”来处理这个值。

问题来了

在期望接收整数的表列上转换和持久化以 DateTime 格式传递的值的最佳方法是什么,反之亦然,用相应的 DateTime 格式覆盖表单字段默认值“时间戳格式”(使DatePicker 可以识别)?

我正在使用 Symfony 3.3.5 和 Twig。

这是一个例子

我已经使用了一种解决方法来达到该范围,但我不能 100% 确定这是一个好习惯...

FormType.php 添加一个带有类的文本字段来挂钩 DatePicker 小部件:

->add('createdAt', TextType::class, [
            'attr' => [
                'class' => 'js-datepicker'
            ],
        ])

Entity setter 看起来像这样:

/**
 * @param mixed $createdAt
 */
public function setCreatedAt($createdAt, $stringToTime = true)
{
    $this->createdAt = ($stringToTime) ? strtotime($createdAt) : $createdAt;
}

这里真正的技巧是额外的 $stringToTime 参数。

最后是controllerAction:

/**
 * @Route("/content/edit/{id}", name="admin_content_edit")
 */
public function editContentAction(Request $request, Content $content)
{
    $date = new \DateTime();
    $date->setTimestamp($content->getCreatedAt());
    $content->setCreatedAt($date->format('d-m-Y'), false);

    $form = $this->createForm(ContentType::class, $content);

    $form->handleRequest($request);
    if ($form->isSubmitted()){
        if ($form->isValid()) {

            $content = $form->getData();

            $em = $this->getDoctrine()->getManager();
            $em->persist($content);
            $em->flush();

            $this->addFlash('success', 'Content updated');

            return $this->redirectToRoute('admin_content_show');
        }
    }


    return $this->render('RootgearBundle:Default:editContent.html.twig', array(
        'contentForm' => $form->createView()
    ));
}

关键部分是这样的:

$date = new \DateTime();
$date->setTimestamp($content->getCreatedAt());
$content->setCreatedAt($date->format('d-m-Y'), false);

这就是我所做的,它就像一个魅力。 但我不知道这是否是正确的方法,或者是否有更好的解决方案。

在此先感谢您的欢迎辞 :)

============= 基于 Alain Tiemblo 建议的新解决方案

在阅读了一些关于 Data Transformer 的文档后,我终于弄清楚了如何使用我的“日期”值

我只对我的 formType 类应用了更改,方法是使用 CallbackTransformer 和 addModelTranformer 对象和闭包。

这也是一种魅力的结果:)

$builder->get('createdAt')
      ->addModelTransformer(new CallbackTransformer(
        function($dateTime) {
          $date = new \DateTime();
          $date->setTimestamp($dateTime);
          return $date->format('d-m-Y');
        },
        function($timestamp) {
          return $timestamp;
        }
      ));

【问题讨论】:

    标签: symfony


    【解决方案1】:

    好消息,Symfony Data Transformers 就是为此而生的!

    创建表单时,您可以添加:

    use Symfony\Component\Form\CallbackTransformer;
    
    // (...)
    
    $builder->get('createdAt')
        ->addModelTransformer(new CallbackTransformer(
            function ($dateModelToView) {
                $date = new \DateTime();
                $date->setTimestamp($dateModelToView);
                return $date;
            },
            function ($dateViewToModel) {
                return $dateViewToModel->getTimestamp();
            }
       ));
    

    并且转换将是全自动的。

    【讨论】:

    • 谢谢阿兰。我读到了这个炉排组件!!它看起来正是我需要的! :)
    【解决方案2】:

    通常您使用一些 ORM(如教义)并且您有数据库表的 DateTime 字段类型,并且生成的实体会自动将它们视为 DateTimes(前端的 html 日期选择器)。

    您根本不需要为此烦恼。

    这里是一个例子:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/basic-mapping.html

    希望对您有所帮助。

    【讨论】:

    • 嗨@Keloo,感谢您的友好回复。是的,事实上第一个版本确实是 DateTime 字段类型。我决定做一个测试,用 Unix TimeStamp 代替它,只是因为它看起来更灵活一些(尤其是在时间计算上)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-04
    相关资源
    最近更新 更多