Symfony DataMapper不更新对象

jdo*_*dog 5 forms symfony

我按照文档使用DataMapper:https://symfony.com/doc/current/form/data_mappers.html 从表单中的3个字段中的1个更新日期:

表格类

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('period_start_daily', DateType::class, [
            'widget' => 'single_text',
            'label' => 'Day',
            'html5' => false,
            'attr' => ['class' => 'js-datepicker'],
            'mapped' => false,
            'required' => false
        ])
        ->add('period_start_weekly', DateType::class, [
            'widget' => 'single_text',
            'label' => 'Week',
            'html5' => false,
            'attr' => ['class' => 'js-datepicker'],
            'mapped' => false,
            'required' => false
        ])
        ->add('period_start_monthly', ChoiceType::class, [
            'required' => true,
            'label' => 'Month',
            'choice_loader' => new CallbackChoiceLoader(function () {
                $months = [];
                for ($i = 0; $i <= 12; $i++) {
                    $month = strtotime('first day of this month + ' . $i . ' months');
                    $months[date('M Y', $month)] = date('Y-m-d', $month);
                }
                return $months;
            }),
            'mapped' => false,
            'required' => false
        ])
...
$builder
        ->setDataMapper($this);
...
public function mapFormsToData($forms, &$data)
{
    /** @var FormInterface[] $forms */
    $forms = iterator_to_array($forms);

    switch (intval($forms['Type']->getViewData())){
        case 1:
            $start = $forms['period_start_daily']->getNormData();
            $end = clone $start;

            break;
        case 2:
            $start = $forms['period_start_weekly']->getNormData();
            $end = clone $start;
            $end->add(new \DateInterval('P6D'));
            break;
        case 3:
            $start = $forms['period_start_daily']->getNormData();
            $end = (new \DateTime(
                strtotime($this->getData()['period_start_monthly']->format('Y-m-d').' last day of month')
            ));
            break;
    }
    $data = (new DataSet())
        ->setPeriodStart($start)
        ->setPeriodEnd($end)
        ->setType($forms['Type']->getNormData())
        ->setUpload($forms['upload']->getNormData());
Run Code Online (Sandbox Code Playgroud)

调节器

    $form = $this->createForm(DataSetType::class, $dataset);

    $form->handleRequest($request->getCurrentRequest());

    if ($form->isSubmitted() && $form->isValid()){
        $dataset
            ->setPeriodStart($form->getNormData()->getPeriodStart())
            ->setPeriodEnd($form->getNormData()->getPeriodEnd());
        $dataset->setType($form->getNormData()->getType());
        $dataset->setActive(false);
        $dataset->setUpload($form->getNormData()->getUpload());
        $dataset->getPeriodStart()->setTime(0, 0, 0);
        $dataset->getPeriodEnd()->setTime(0, 0, 0);

        $em->persist($dataset);
        $em->flush();
Run Code Online (Sandbox Code Playgroud)

我希望DataMapper直接更新我的对象,但是我仍然需要复制来自$ form-> getNormData()的数据.

Symfony版本是4.2

Krz*_*ski 2

我下载了你的项目来调试它,我发现了一个错误 - 很难检测到:)我开始认为 Symfony 4 可能有问题,但事实并非如此。一切都很好,一切都很好。

\n\n

看:

\n\n

在此输入图像描述

\n\n
\n

spl_object_hash \xe2\x80\x94 返回给定对象的哈希 ID

\n\n

该函数返回对象的唯一标识符。这个id可以用作存储对象的散列键,或者用于标识对象,只要该对象不被破坏。一旦对象被销毁,它的哈希值就可以被其他对象重用。

\n
\n\n

$beforeHash并且$afterHash具有不同的值 - 因此,它不是同一个对象

\n\n

DataSetType.php(第 138 行)中,您创建了DataSet一个丢失对作为第二个参数传递的先前对象的引用的新实例mapFormsToData

\n\n

在此输入图像描述

\n\n

您应该修改$data参数中的对象,而不是创建 的新实例DataSet

\n\n

步骤1:

\n\n

更改此代码:

\n\n
$data = (new DataSet())\n        ->setPeriodStart($start)\n        ->setPeriodEnd($end)\n        ->setType($forms[\'Type\']->getNormData())\n        ->setUpload($forms[\'upload\']->getNormData())\n        ->setActive($forms[\'active\']->getNormData())\n    ;\n
Run Code Online (Sandbox Code Playgroud)\n\n

对于这段代码:

\n\n
$data->setPeriodStart($start)\n     ->setPeriodEnd($end)\n     ->setType($forms[\'Type\']->getNormData())\n     ->setUpload($forms[\'upload\']->getNormData())\n     ->setActive($forms[\'active\']->getNormData());\n
Run Code Online (Sandbox Code Playgroud)\n\n

第2步:

\n\n

从控制器中删除不必要的代码。create方法应该如下所示:

\n\n
public function create(RequestStack $request)\n{\n    $dataset = new DataSet();\n\n    $form = $this->createForm(DataSetType::class, $dataset);\n\n    $form->handleRequest($request->getCurrentRequest());\n\n    if ($form->isSubmitted() && $form->isValid()){\n        $em = $this->getDoctrine()->getManager();\n        $em->persist($dataset);\n        $em->flush();\n\n        if ($dataset->getUpload()) {\n            $em->getRepository(\'App:DataSet\')\n                ->disableUploadOthers($dataset->getId(), $dataset->getType());\n        }\n        $this->addFlash(\'success\', \'Dataset created.\');\n        return $this->redirectToRoute(\'dataset_index\');\n    }\n\n    return $this->render(\'dataset/create.html.twig\', [\n        \'form\' => $form->createView()\n    ]);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

中的值$dataset必须在没有您帮助的情况下更改:)

\n\n
\n\n

文档可能有点令人困惑,但请注意文档中的示例基于不可变对象

\n\n

在此输入图像描述

\n\n

顺便说一句 - 最好扩展文档并展示 DataMapper 如何与 Doctrine 模型一起工作......

\n