CraueFormFlowBundle-以当前形式使用上一步的数据

问题描述

我在Symfony3中将CraueFormFlowBundle用于多步骤表单,到目前为止,它仍然有效。第一步,有一个添加个人数据的表单,例如姓名,生日等。现在,我想添加第二步,该表单将检查是否存在具有相似数据的人。如果没有,则应跳过该步骤;如果有,则应与可能的人员进行选择。

问题是我无法使用预览步骤的数据进行检查。 我将在此处提供一些示例代码(不完整):

实体

<?php
declare(strict_types=1);

namespace TestBundle\Entity;


use DateTime;

class Person
{
    /** @var int */
    protected $id;
    /** @var string */
    protected $firstname;
    /** @var string */
    protected $lastname;
    /** @var DateTime */
    protected $birthday;

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

    /**
     * @param int $id
     */
    public function setId(int $id): void
    {
        $this->id = $id;
    }

    /**
     * @return string
     */
    public function getFirstname(): string
    {
        return $this->firstname;
    }

    /**
     * @param string $firstname
     */
    public function setFirstname(string $firstname): void
    {
        $this->firstname = $firstname;
    }

    /**
     * @return string
     */
    public function getLastname(): string
    {
        return $this->lastname;
    }

    /**
     * @param string $lastname
     */
    public function setLastname(string $lastname): void
    {
        $this->lastname = $lastname;
    }

    /**
     * @return DateTime
     */
    public function getBirthday(): DateTime
    {
        return $this->birthday;
    }

    /**
     * @param DateTime $birthday
     */
    public function setBirthday(DateTime $birthday): void
    {
        $this->birthday = $birthday;
    }
    
    /**
     * @return string
     */
    public function getName(): string
    {
        return $this->firstname.' '.$this->lastname;
    }
}
<?php
declare(strict_types=1);

namespace TestBundle\Entity;


class Basicdata
{
    /** @var Person */
    protected $person;
    
    /**
     * other fields that not from the person
     */
    
    /**
     * @return Person|null
     */
    public function getPerson(): ?Person
    {
        return $this->person;
    }

    /**
     * @param Person|null $person
     */
    public function setPerson(?Person $person): void
    {
        $this->person = $person;
    }
}

表格

<?php
declare(strict_types=1);

namespace TestBundle\Form;

use TestBundle\Entity\Basicdata;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class BasicdataType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder,array $options): void
    {
        $builder->add('person',PersonType::class,[
            'required' => true,'label'    => 'Person data',]);
        
        /**
         * Other form fields
         */
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => Basicdata::class,]);
    }
}
<?php
declare(strict_types=1);

namespace TestBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use TestBundle\Entity\Person;

class PersonType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder,array $options): void
    {
        $builder->add('firstname',TextType::class,]);
        $builder->add('lastname',]);
        $builder->add('birthday',DateType::class,]);
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => Person::class,]);
    }
}
<?php
declare(strict_types=1);

namespace TestBundle\Form;

use ArrayObject;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use TestBundle\Entity\Basicdata;

class PersonExistType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder,ChoiceType::class,[
            'choices' => $options['persons'],'choice_value' => 'id','choice_label' => 'name','required' => true,]);
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class'    => Basicdata::class,'persons'  => new ArrayObject(),]);
    }
}

流程

<?php
declare(strict_types=1);

namespace TestBundle\Flow;


use ArrayObject;
use Craue\FormFlowBundle\Form\FormFlow;
use TestBundle\Entity\Basicdata;
use TestBundle\Entity\Person;
use TestBundle\Form\BasicdataType;
use TestBundle\Form\PersonExistType;


class FormularFlow extends FormFlow
{
    /**
     * @return ArrayObject|Person[]
     */
    public function getDoublePersons(Basicdata $data): ArrayObject
    {
        // Don't work like this - its only a placeholder to show that there should get persons from the database or whatever depends on the fromular data before
        return $db->getDoublePersons($data->getPerson()->getFirstname(),$data->getPerson()->getLastname(),$data->getPerson()->getBirthday());
    }

    protected function loadStepsConfig()
    {
        return [
            [
                'label'     => 'Basic data','form_type' => BasicdataType::class,],[
                'label'     => 'Check Person','form_type' => PersonExistType::class,'form_options' => [
                    // That don't work,because the form data is not the saved one from the previews step
                    'persons' => $this->getDoublePersons($this->getFormData())
                ],'skip' => function ($step,FormFlow $flow) {
                    // That works with the new form data
                    return $this->getDoublePersons($flow->getFormData())->count() === 0;
                }
            ],// Other steps
        ];
    }
}

控制器

<?php
declare(strict_types=1);

namespace TestBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

/**
 * @Route("/form")
 */
class FormController extends Controller
{
    public function formAction(): Response
    {
        // The FormularFlow is set in the config.yml
        $flow = $this->get('formular_flow');

        // There are prefilled data from another database getting as Basicdata Entity ($db not working,only for demonstrate)
        $flow->bind($db->getDataWithInitalPersonDateFromSomewhereElse());
        $form = $flow->createForm();

        if ($flow->isValid($form)) {
            $flow->saveCurrentStepData($form);
            if ($flow->nextStep()) {
                $form = $flow->createForm();
            } else {
                // Save data in database and redirect
            }
        }

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

FormularFlow类中,必须填写表单选项persons。为此,我需要来自上一步的表单数据,在skip选项中,我可以使用闭包来获取它并起作用,但是无法在persons选项上使用闭包。所以我尝试了不同的事情:

  • 将人员从控制器注入FormularFlow。但这是行不通的,因为在Controller中,我只能在使用有效方法之后才能访问表单数据,但是该表单将在之前生成。
  • 使用流程中的表单数据不起作用,因为它不是上一步中的表单数据。

如果某个地方有解决此问题的方法,那就太好了。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)