我在symfony中有一个动态表单。目前我有一个外部服务,数据存在这个服务提供了一种呈现数据表单的方法,但我需要将我的bussines逻辑集成到我的应用程序中。
为了解决这个问题,我实现了一个注释和一个CustomType。注释是外部服务中表的名称的简单持有者
在我的应用中,我有一个实体
/**
* Person
*
* @ORM\Table("person")
* @ORM\Entity
* @EService("person_data")
*/
class Person extends AbstractEntityEService
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**/
}
/**
* AbstractEntityEService
*
*/
abstract AbstractEntityEService
{
/**
* @var integer
*
* @ORM\Column(name="uuid", type="string")
*/
protected $uuid;
/**
* Holder for the data
protected $data;
/* setters and getters... */
}
外部服务在我存储数据时提供uuid
,使用此uuid
我可以在我的视图中打印字段,使用此uuid我可以更新数据。
这是我的CustomType
class ExternalType extends AbstractType {
/**
* @var Reader
*/
private $reader;
/**
* @var ExternalService
*/
private $ts;
public function __construct(Reader $reader, ExternalService $ts){
$this->reader = $reader;
$this->ts = $ts;
}
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function(FormEvent $event) use ($options) {
$annotation = $this->reader->getClassAnnotation(
new \ReflectionClass($options['class']),
'MyBundle\Lib\Annotation\EServiceAnnotation'
);
// this is only form a empty form
if (null === $event->getData()) {
// here get the annotated value from entity and get a uuid
$event->setData($this->ts->getForm($annotation->getformName()));
}
$event->getForm()->getParent()->add('data', 'collection', array(
'allow_add' => true,
'label' => false
));
});
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver
->setDefaults(array(
'required' => false,
'error_bubbling' => true
))
->setRequired(array(
'class',
));
}
/**
* @inheritdoc
*/
public function getName()
{
return 'external';
}
/**
* @inheritdoc
*/
public function getParent()
{
return 'hidden';
}
}
这是CustomType
的模板{% block external_widget %}
{% spaceless %}
<div data-form-name="{{ form.parent.vars.name }}" data-form-uuid="{{uuid}}"></div>
{% set type = type|default('hidden') %}
{{ block('form_widget_simple') }}
{% endspaceless %}
{% endblock external_widget %}
我将我的ExternalType注册服务用于我的主要表单PersonType
class AsociacionType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('uuid', 'external', array('class' => $options['data_class']));
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'MyBundle\Entity\Person'
));
}
/**
* @return string
*/
public function getName()
{
return 'my_bundle_person';
}
}
在最后我使用doctrine.event_subscriber
postLoad
:使用uuid进行呼叫外部服务填充我的实体中的数据属性prePersist
:用于保留用户发送到外部服务的数据preUpdate
:用于更新用户发送到外部服务的数据这里的事件
public function postLoad(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if ($entity instanceof AbstractEntityEService && null !== $entity->getUuid())
{
$t = $this->externalService->get($entity->getUuid());
$entity->setData((array)$t->getData());
}
}
public function prePersist(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if ($entity instanceof AbstractEntityEService) {
$t = $this->externalService->persist($entity->getData(), $entity->getUuid());
$entity->setUuid($t->getUuid());
}
}
public function preUpdate(LifecycleEventArgs $args)
{
$this->prePersist($args);
}
新的和创造工作正常。但是当我要以未知原因更新数据时 preUpdate
事件永远不会被称为。我认为这是因为表格并不意味着数据已经改变。 我需要知道如何告诉Symfony the form has changed