Symfony DataMapper无法更新对象

时间:2019-01-14 09:28:26

标签: 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());

控制器

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

我希望DataMapper直接更新我的对象,但是我仍然必须复制$ form-> getNormData()中的数据。

Symfony版本为4.2

1 个答案:

答案 0 :(得分:1)

我下载了your project进行调试,但发现一个错误-很难发现:)我开始认为Symfony 4可能有问题,但不是。一切都很好,一切都很好。

看:

enter image description here

  

spl_object_hash —返回给定对象的哈希ID

     

此函数返回对象的唯一标识符。只要未破坏对象,此id可用作存储对象或标识对象的哈希键。一旦对象被销毁,其哈希可以重新用于其他对象。

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

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

enter image description here

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

第1步:

更改此代码:

$data = (new DataSet())
        ->setPeriodStart($start)
        ->setPeriodEnd($end)
        ->setType($forms['Type']->getNormData())
        ->setUpload($forms['upload']->getNormData())
        ->setActive($forms['active']->getNormData())
    ;

这段代码:

$data->setPeriodStart($start)
     ->setPeriodEnd($end)
     ->setType($forms['Type']->getNormData())
     ->setUpload($forms['upload']->getNormData())
     ->setActive($forms['active']->getNormData());

第2步:

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

public function create(RequestStack $request)
{
    $dataset = new DataSet();

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

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

    if ($form->isSubmitted() && $form->isValid()){
        $em = $this->getDoctrine()->getManager();
        $em->persist($dataset);
        $em->flush();

        if ($dataset->getUpload()) {
            $em->getRepository('App:DataSet')
                ->disableUploadOthers($dataset->getId(), $dataset->getType());
        }
        $this->addFlash('success', 'Dataset created.');
        return $this->redirectToRoute('dataset_index');
    }

    return $this->render('dataset/create.html.twig', [
        'form' => $form->createView()
    ]);
}

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


Documentation可能有点令人困惑,但请注意,example from documentation基于不可变的对象

enter image description here

顺便说一句-扩展文档并说明DataMapper如何与Doctrine模型一起使用...