问题描述
我在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 (将#修改为@)