我目前正在尝试为表单类型实现一个密钥对值,该值与FOSRestBundle一起使用,以允许发送如下请求:
{
"user": {
"username": "some_user",
"custom_fields": {
"telephone": "07777",
"other_custom_field": "other custom value"
}
}
}
此后端表示如下:
用户
id,username,customFields
CustomUserField
id,field
CustomUserFieldValue
user_id,field_id,value
我目前制作了如下自定义表格:
<?php
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('username')
->add(
'custom_fields',
'user_custom_fields_type'
)
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
array(
'data_class' => 'Acme\DemoBundle\Entity\User',
'csrf_protection' => false,
)
);
}
public function getName()
{
return 'user';
}
}
我的user_custom_fields_type
:
<?php
class CustomUserFieldType extends AbstractType
{
private $em;
/**
* @param EntityManager $em
*/
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$fields = $this->em->getRepository('AcmeDemoBundle:CustomUserField')->findAll();
foreach($fields as $field) {
$builder->add($field->getField(), 'textarea');
}
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
array(
'invalid_message' => 'The selected custom field does not exist'
)
);
}
public function getParent()
{
return 'collection';
}
public function getName()
{
return 'user_custom_fields_type';
}
}
这一直给我一个额外字段的错误。我在CustomUserFieldType
中添加了哪些内容。我怎样才能使这个工作?
注意:这是实际代码的简化版本,我尝试删除所有不相关的代码。
答案 0 :(得分:0)
您需要使用表单侦听器向表单添加动态字段:
http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html
在你的情况下,PRE_SET_DATA
就足够了。像这样:
$em = $this->em;
$builder->addEventListener(FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ( $em )
{
// get the form
$form = $event->getForm();
// fetch your data here
$fields = $em->getRepository('AcmeDemoBundle:CustomUserField')->findAll();
foreach($fields as $field)
{
// make sure you add the new fields to $form and not $builder from this event
$form->add($field->getField(), 'textarea');
}
});
答案 1 :(得分:0)
我有完全相同的问题,最后通过手动解析自定义字段来解决它。如果有其他解决方案,请分享:)
在UserType表单中:
$builder->addEventListener(FormEvents::POST_SET_DATA,
function (FormEvent $event) use ( $oEm, $oUser )
{
$oForm = $event->getForm();
$aFields = $oEm->getRepository('MyDBBundle:CustomUserField')->findAll();
/** @var CustomUserField $oField */
foreach($aFields as $oField)
{
$oForm->add(
'custom__'.$oField->getKey(),
$oField->getType(),
array(
'label' => $oField->getField(),
'mapped' => false,
'required' => false
)
);
/** @var CustomUserFieldValue $oFieldValue */
$oFieldValue = $oEm->getRepository('MyDBBundle:CustomUserFieldValue')->findOneBy(array('user' => $oUser, 'field' => $oField));
if(null !== $oFieldValue) {
$oForm->get('custom__' . $oField->getKey())->setData($oFieldValue->getValue());
}
}
}
);
然后,在处理提交表单请求的控制器操作中:
// Handle custom user fields
foreach($oForm->all() as $sKey => $oFormData)
{
if(strstr($sKey, 'custom__'))
{
$sFieldKey = str_replace('custom__', '', $sKey);
$oField = $oEm->getRepository('MyDBBundle:CustomUserField')->findOneBy(array('key' => $sFieldKey));
/** @var CustomUserFieldValue $oFieldValue */
$oFieldValue = $oEm->getRepository('MyDBBundle:CustomUserFieldValue')->findOneBy(array('user' => $oEntity, 'field' => $oField));
if($oFieldValue === null)
{
$oFieldValue = new CustomUserFieldValue();
$oFieldValue->setUser($oEntity);
$oFieldValue->setField($oField);
}
$oFieldValue->setValue($oFormData->getData());
$oEm->persist($oFieldValue);
}
}
(假设CustomUserField实体中既有“field”属性又有“key”; key 是您字段的唯一无空间标识符,字段是人类友好和可读的字段标签。)
这是有效的,希望它能有所帮助。但是,想知道是否有人有更好的解决方案。 :)