我创建了一个集成测试来调试一个实际问题,该问题似乎源于从Symfony 3.3升级到3.4。问题是,我在实体上的所有array
字段(Doctrine ORM注释为字段上的类型json_array
,并在Postgres中存储为json
(都应该由我提交的$requestEntity
中的值填充,但它们都变成了null
。类型定义中有错吗?我真的不确定实体类是如何与";填充";实体与表单类型定义的关系,因此我将列出两者的相关位。
编辑:澄清此数据是什么
这里的$requestEntity
不是文字用户输入,而是从API端点解析的JSON。我不确定使用表单功能是否是验证和处理非表单数据的正确方法,但这是写这篇文章的人的选择。
scoreCols
始终是submit()
之后的null
的代码
$requestEntry = array(
'id' => 'C4F1D2A3-762D-4548-B0E3-C0B3912FC02C',
'score_cols' =>
array(
0 => 'REPS',
1 => 'PAUSE',
2 => 'KG_WEIGHTS',
)
// other fields trimmed for brevity
);
$model = new ExerciseInfo();
$formFactory = $container->get("form.factory");
$form = $formFactory->create(ApiExerciseInfoType::class, $model);
$form->submit($requestEntry);
/**
* @var $data ExerciseInfo
*/
$entity = $form->getData();
// $cols should be something like ["REPS", "PAUSE", "REPS"], but is always null!
$cols = $entity->getScoreCols();
实体类:ExerciseInfo
class ExerciseInfo
{
/**
* @var string
*
* @ORMColumn(name="id", type="guid")
* @ORMId
* @AssertNotNull()
*/
private $id;
/**
* @var array
*
* @ORMColumn(name="score_cols", type="json_array", nullable=true)
* @AssertNotBlank()
*/
private $scoreCols; // will contain array of types eg: ["REPS", "KG_WEIGHTS", "PAUSE"]
...
表单类型定义
class ApiExerciseInfoType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('id', HiddenType::class)
->add('exercise_id', EntityType::class, [
'class' => 'PETEBackendBundleEntityExercise',
'property_path' => 'exercise',
])
->add('notes_sets', null, [])
->add('exercise_notes', null, [])
->add('score_cols', TextType::class, [
'property_path' => 'scoreCols'
])
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'MyProjBackendBundleEntityExerciseInfo',
'csrf_protection' => false,
'allow_extra_fields' => true,
));
}
}
技术详细信息
symfony/symfony v3.4.49
symfony/phpunit-bridge v3.4.47
doctrine/annotations 1.13.2
doctrine/cache 1.12.1
doctrine/collections 1.6.8
doctrine/common 2.13.3
doctrine/data-fixtures 1.5.2
doctrine/dbal 2.13.7
doctrine/deprecations v0.5.3
doctrine/doctrine-bundle 1.12.13
doctrine/doctrine-cache-bundle 1.4.0
doctrine/doctrine-fixtures-bundle v2.4.1
doctrine/doctrine-migrations-bundle v1.3.2
doctrine/event-manager 1.1.1
doctrine/inflector 1.4.4
doctrine/instantiator 1.4.0
doctrine/lexer 1.2.2
doctrine/migrations v1.8.1
doctrine/orm 2.7.5
doctrine/persistence 1.3.8
doctrine/reflection 1.2.2
Symfony在其3.4.21版本中做出了突破性的改变,对TextType
的允许范围更加严格。当我更新到最新版本3.4.49时,我被刺痛了。它现在正在从标量类型中筛选数组。
在一个相关的问题中,Alexander Schranz发布了一个变通方法:
class UnstructuredType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'compound' => false,
'multiple' => true,
));
}
}
这正是我所需要的:我只是用UnstructuredType
和presto代替了TextType
的使用。正如Cerad在评论中提到的那样,一般方法可能是错误的,人们可能应该选择数据转换器(我还没有研究过(。