所以我有一个基本形式:
checklist
具有特定字段ChecklistModel.php
。我创建了一个模型类,它描述了清单中的所有可能选项
class ChecklistModel {
/** @var string **/
protected $clientSatisfied;
// ... getters and setters
}
ChecklistFormType.php
然后,我专门为Checklist创建了一个表单类型。
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('clientSatisfied', ChoiceType::class, array(
'choices' => array(
'yes' => 'yes',
'no' => 'no'
),
'choices_as_values' => true,
))
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => ChecklistModel::class
));
}
ChecklistModel
我想将清单存储为数据库中的简单JSON字符串,但我想使用ChecklistFormType
来确保清单中的所有字段都正确提交。
我的问题是如何告诉Symfony使用checklist
作为基本格式->add('checklist', ChecklistFormType::class);
属性的字段类型?
我尝试过像
这样的东西The form's view data is expected to be an instance of class PT\MyBundle\Models\Invoice\ChecklistModel, but is a(n) string. You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms a(n) string to an instance of PT\MyBundle\Models\Invoice\ChecklistModel
但我得到了以下错误
{{1}}
答案 0 :(得分:1)
您必须在错误消息中指定数据类,并与de / serializer一起定义数据转换器。 Symfony documentation
答案 1 :(得分:1)
根据我上面的评论,我建议不要在表单类型中进行数据转换(虽然它当然可以),而是使用json_array type
进行封装模型。 / p>
这样只有该模型才能真正了解数据的持久性。
两个相关模型:
src/AppBundle/Entity/FooModel.php
<?php
declare(strict_types=1);
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity()
*/
class FooModel
{
// other properties (firstName, lastName, ...)
/**
* @var array
*
* @ORM\Column(type="json_array")
*/
private $checklist = [];
/**
* @param ChecklistModel $checklist
*/
public function setChecklist(ChecklistModel $checklist)
{
$this->checklist = $checklist->toArray();
}
/**
* @return ChecklistModel
*/
public function getChecklist(): ChecklistModel
{
return ChecklistModel::fromArray($this->checklist);
}
}
ChecklistModel
实施上述方法:
src/AppBundle/Entity/ChecklistModel.php
<?php
declare(strict_types=1);
namespace AppBundle\Entity;
class ChecklistModel
{
// properties and getters/setters
/**
* @param array $data
*
* @return ChecklistModel
*/
public static function fromArray(array $data): ChecklistModel
{
$result = new self;
foreach (get_class_vars(self::class) as $k => $v) {
if (isset($data[$k])) {
$result->$k = $data[$k];
}
}
return $result;
}
/**
* @return array
*/
public function toArray()
{
return get_object_vars($this);
}
}
表单类型:
src/AppBundle/Form/FooFormType.php
<?php
declare(strict_types=1);
namespace AppBundle\Form;
use AppBundle\Entity\FooModel;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type as FormType;
class FooFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstName', FormType\TextType::class)
->add('lastName', FormType\TextType::class)
->add('checklist', ChecklistFormType::class)
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => FooModel::class,
'empty_data' => new FooModel(),
]);
}
}
src/AppBundle/Form/ChecklistFormType.php
<?php
declare(strict_types=1);
namespace AppBundle\Form;
use AppBundle\Entity\ChecklistModel;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type as FormType;
class ChecklistFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('clientSatisfied', FormType\ChoiceType::class, [
'choices' => [
'yes' => 'yes',
'no' => 'no'
],
'choices_as_values' => true,
])
->add('clientNewCustomer', FormType\ChoiceType::class, [
'choices' => [
'yes' => 'yes',
'no' => 'no'
],
'choices_as_values' => true,
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => ChecklistModel::class,
'empty_data' => new ChecklistModel(),
]);
}
}
示例用法
public function indexAction(Http\Request $request)
{
$em = $this->getDoctrine()->getManager();
$data = new Entity\FooModel();
$form = $this
->createForm(FooFormType::class, $data)
->handleRequest($request)
;
if ($form->isSubmitted() && $form->isValid()) {
$em->persist($data);
$em->flush();
}
return $this->render('default/index.html.twig', [
'form' => $form->createView(),
'data' => $form->getData(),
]);
}
这样ChecklistFormType
不需要知道关于json或其他什么的数据。 ChecklistModel
进入并出现,没有任何意外。
那就是说embeddables可能是更好的选择。