在我的Symfony 2.7.10项目中,我有一个实体表单,它通过queryBuilder从数据库加载一个物质对象。
$builder
->add('size', 'entity', [
'class' => 'AppBundle\Entity\Material',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('m')
->select('m')
->where('m.idproduct = :idproduct')->setParameter('idproduct', $this->product->getIdProduct())
->groupBy('m.size')
->orderBy('m.id');
},
'choice_label' => 'size',
'expanded' => true,
'constraints' => new NotBlank(),
]);
此外,我预先设置一个表单字段,在用户选择材料大小后动态加载。 这是通过EventSubscriber
完成的$builder->addEventSubscriber(new AddEndTermsSubscriber('size', $options['locale']));
该课程如下:
...
class AddEndTermsSubscriber implements EventSubscriberInterface
{
private $propertySize;
private $locale;
public function __construct($propertySize, $locale)
{
$this->propertySize = $propertySize;
$this->locale = $locale;
}
public static function getSubscribedEvents()
{
return [
FormEvents::PRE_SET_DATA => 'preSetData',
];
}
private function addFormField(FormInterface $form, Material $material)
{
$form->add('endterm', 'entity', [
'class' => 'AppBundle\Entity\MaterialT',
'query_builder' => function (EntityRepository $er) use ($material) {
return $er->createQueryBuilder('t')
->select('mt')
->from('AppBundle:MaterialT', 'mt')
->leftJoin('mt.m', 'm')
->where('m.size = :size')
->setParameter('size', $material->getSize());
},
'expanded' => true,
'mapped' => false,
'required' => false,
'placeholder' => false,
'choice_label' => 'name'.$this->locale,
]);
}
public function preSetData(FormEvent $event)
{
$data = $event->getData();
$form = $event->getForm();
if ($data === null) {
return;
}
$accessor = PropertyAccess::createPropertyAccessor();
$formMaterial = $accessor->getValue($data, $this->propertySize);
$material = ($formMaterial) ? $formMaterial : new Material();
$this->addFormField($form, $material);
}
}
通过ajax Action我在用户选择材料后加载endTerms的表单字段。
提交表单后,我将材料实体和选定的endTerm存储在会话中,并重定向到下一个表单步骤:
if ($form->get('size')->getData() != null &&
$request->request->get('endterm') != null) {
$request->getSession()->set('token/size', $form->get('size')->getData());
$idEndterm = $request->request->get('endterm');
$endterm = $this->getDoctrine()->getRepository('AppBundle:MaterialT')
->createQueryBuilder('mt')
->leftJoin('mt.m', 'm')
->where('m.id = :id')
->setParameter('id', $idEndterm)
->getQuery()
->getSingleResult();
$request->getSession()->set('token/endterm', $endterm);
//...
}
问题: 用户应该可以编辑他的配置,因此在下一步他可以“编辑他的配置”并返回我通过重定向到表格的上述操作。
public function materialDetailsAction(Request $request)
{
$material = new Material();
$product = $request->getSession()->get('token/product');
$form = $this->createForm(new MaterialType($product), $material, ['locale' => $request->getLocale()]);
//...
}
如何实现存储的会话值预先填写到表单?
最佳做法是通过$ options参数将它们路由到表单,然后执行if else验证吗?
热烈欢迎任何有关解决方案的提示或如何做得更好。 感谢
答案 0 :(得分:0)
我终于找到了一个有效的解决方案。
问题的快速摘要:
给我很多帮助的提示是: - Symfony2 Setting a default choice field selection
现在代码......
在导致配置表格的行动中,我添加了一些会话预先配置
// create session cart
$request->getSession()->set('token', []); // token reset per configuration
if (!$request->getSession()->has('cart')) {
$request->getSession()->set('cart', []);
}
PersistentObject
以在FormType和依赖EventSubscribers
稍后在提交条件中,我只更新购物车会话数组。
public function materialDetailsAction(Request $request)
{
// back to start if session empty
if ($request->getSession()->get('token/product') == null) {
return $this->redirectToRoute('configurator_product');
}
$product = $request->getSession()->get('token/product');
// persistence manager
PersistentObject::setObjectManager($this->getDoctrine()->getManager());
$material = new Material();
$form = $this->createForm(new MaterialType($product), $material, [
'locale' => $request->getLocale(),
'sessionCart' => ($request->getSession()->has('editId')) ? $request->getSession()->get('token') : null,
]);
// ... validation etc.
// update session for shopping cart
$shoppingCart = $request->getSession()->get('cart');
if ($request->getSession()->has('editId')) {
$shoppingCart[$request->getSession()->get('editId') -1] = $request->getSession()->get('token');
} else {
$shoppingCart[] = $request->getSession()->get('token');
}
$request->getSession()->set('cart', $shoppingCart);
// ... redirect
}
在表单类型中,我使用'sessionCart' => null,
默认值扩展configureOptions数组
data
选项,它是假的(如果会话值为空)或者我会得到这样的对象: $defaultData = ($options['sessionCart'] != null)
? PersistentObject::getObjectManager()->getRepository('AppBundle:Material')
->find($options['sessionCart']['size']->getId())
: false;
按下编辑按钮
按钮>> ajax
// get selected leaflet id and current session
$id = $request->request->get('id');
$session = $request->getSession();
// get selected configuration (table ID != array ID)
$selectedToken = $session->get('cart')[$id - 1];
// reset token
$request->getSession()->set('token', []);
$request->getSession()->set('editId', $id);
// set token from selected configuration
foreach ($selectedToken as $key => $value) {
$session->set('token/'.$key, $value);
}
return new JsonResponse();
希望这可以帮助将来的某个人,或者如果有人有一些美分可以添加(增强等),我们热烈欢迎您!