Forms 从一个选择构建多个表单
全部 我想问一下,是否有可能在一个页面上有多个表单(现在每个选择选项),而不是多个选择字段 情况是:我有一个与服务有@ManyToMany bi关系的用户和“User\u Services”关系存储表,但扩展了附加字段,如带有UserService实体类的Forms 从一个选择构建多个表单,forms,orm,symfony,many-to-many,Forms,Orm,Symfony,Many To Many,全部 我想问一下,是否有可能在一个页面上有多个表单(现在每个选择选项),而不是多个选择字段 情况是:我有一个与服务有@ManyToMany bi关系的用户和“User\u Services”关系存储表,但扩展了附加字段,如带有UserService实体类的min\u price,max\u price,等等 我认为在我的特殊情况下,更好的用户体验是使用带有复选框、服务名称和价格字段的表布局,并带有一个保存按钮,但我不知道如何创建多个表单,其中每个表单对应于选择列表中的一个选项,然后是该选项的其他
min\u price
,max\u price
,等等
我认为在我的特殊情况下,更好的用户体验是使用带有复选框、服务名称和价格字段的表布局,并带有一个保存按钮,但我不知道如何创建多个表单,其中每个表单对应于选择列表中的一个选项,然后是该选项的其他字段
谢谢。在这种情况下,我认为您应该使用
集合
类型,它可以用来处理多对多关系
如果我理解得很好,您希望为给定的用户处理用户服务的列表
然后,您必须制作如下内容:
- 1、创建一个
UserServiceType
,它将表示用户和服务之间的关系(加上其最低价格、最高价格等):
类UserServiceType扩展了AbstractType
{
公共函数buildForm(FormBuilder$builder,数组$options)
{
$builder
->添加(‘最低价格’、‘货币’)
->添加(‘最高价格’、‘货币’)
;
}
公共函数getDefaultOptions()
{
返回数组('data_class'=>'Entity\UserService');
}
}
- 2、将其注册为表格类型:
//app/config/config.yml(例如)
服务:
用户\服务\类型:
类别:UserServiceType
标签:
-{name:form.type,别名:user\u service}
- 3、配置
UserType
以处理此集合:
class用户类型扩展了AbstractType
{
公共函数buildForm(FormBuilder$builder,数组$options)
{
$builder
->添加('services','collection',数组(
'type'=>'user\u service',//这是上面注册的表单类型的id
“允许添加”=>true,
“允许删除”=>true,
“原型”=>正确,
))
;
}
公共函数getDefaultOptions()
{
返回数组('data_class'=>'Entity\User');
}
}
假设您有一组服务,并且希望显示它们
你会怎么做
我的解决方案:
控制器:
用户服务类型:
服务类型:
ServiceDetailsType:
最令人惊奇的是,所有这些工作!非常感谢Florian花时间在我身上,让我不断思考解决方案,并为不清楚的问题(如果是)道歉。我认为,Symfony文档应该更新为更多不同的表单嵌入/收集示例,如下所示
干杯,
迪玛。谢谢你的回复,我今天晚上会试试看,好像“收藏”根本不起作用,我试着简化任务$生成器->添加('服务);-渲染倍增选择。但是$builder->add('services','collection',array('type'=>'text');-除“服务”标签外,不呈现任何内容。我使用{form_widget(form)}}来呈现表单。我还尝试了$builder->add('services','collection',array('type'=>newserviceType());在ServiceType()类($builder->add('name')中只有服务的“name”)。但也没什么。奇怪,非常奇怪,它不起作用,或者我错过了一些重要的东西。我甚至试过Symfony2书中的例子(或者说烹饪书,我不记得了),但都不管用。我使用的是2.0.10 Symfony。我认为您必须将UserServiceType
注册为服务,并将其标记为表单.type
。这将使此类型如下所示:->添加('services','collection',array('type'=>'user\u service')
。请参阅我的更新答案。
class DefaultController extends Controller
{
public function indexAction(Request $request)
{
/** @var $em \Doctrine\ORM\EntityManager */
$em = $this->get('doctrine.orm.entity_manager');
$services = $em->getRepository('ThestudioscheduleProfileBundlesServiceBundle:Service')->findAll();
$user = $this->get('security.context')->getToken()->getUser();
$form = $this->createForm(new UserServiceType($services, $user->getServiceDetails()));
if ('POST' == $request->getMethod()) {
$form->bindRequest($request);
if ($form->isValid()) {
$data = $form->getData();
$em->getConnection()->beginTransaction();
try {
foreach ($data['services'] as $serviceDetails) {
// if service is selected
if ($serviceDetails['id']) {
$serviceDetails['details']->setUser($user);
$serviceDetails['details']->setService($em->getRepository('ThestudioscheduleProfileBundlesServiceBundle:Service')->find($serviceDetails['service']));
$serviceDetails['details'] = $em->merge($serviceDetails['details']);
} else {
// if the entity is exist but user unchecked it - delete it
if ($serviceDetails['details']->getId()) {
$serviceDetails['details'] = $em->merge($serviceDetails['details']);
$em->remove($serviceDetails['details']);
}
}
}
$em->flush();
$em->getConnection()->commit();
// TODO: display success message to user
return $this->redirect($this->generateUrl('ThestudioscheduleProfileBundlesServiceBundle_homepage'));
} catch (\Exception $e) {
$em->getConnection()->rollback();
$em->close();
var_export($e->getMessage());die;
// TODO: log exception
// TODO: display something to user about error
}
}
}
return $this->render('ThestudioscheduleProfileBundlesServiceBundle:Default:index.html.twig', array(
'form' => $form->createView()
));
}
}
class UserServiceType extends AbstractType
{
private $services;
private $userServiceDetails;
public function __construct($services, $userServiceDetails)
{
$this->services = $services;
$this->userServiceDetails = $userServiceDetails;
}
/**
* @param \Symfony\Component\Form\FormBuilder $builder
* @param array $options
* @return void
*/
public function buildForm(FormBuilder $builder, array $options)
{
// all application services
$builder->add('services', 'collection');
foreach ($this->services as $key => $service) {
$serviceType = new ServiceType($service, null);
foreach ($this->userServiceDetails as $details) {
if ($service == $details->getService()) {
$serviceType->setUserServiceDetails($details);
}
}
$builder->get('services')->add('service_' . $key, $serviceType);
}
}
/**
* Returns the name of this type.
*
* @return string The name of this type
*/
public function getName()
{
return 'profile_user_service';
}
}
class ServiceType extends AbstractType
{
private $service;
private $userServiceDetails;
public function __construct($service, $userServiceDetails)
{
$this->service = $service;
$this->userServiceDetails = $userServiceDetails;
}
/**
* @param \Symfony\Component\Form\FormBuilder $builder
* @param array $options
* @return void
*/
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('id', 'checkbox', array(
'label' => $this->service->getName(),
'required' => false))
->add('service', 'hidden')
->add('details', new ServiceDetailsType($this->userServiceDetails));
$values = array('service' => $this->service->getId());
if (null !== $this->userServiceDetails) {
$values = array_merge($values, array('id' => true));
}
$builder->setData($values);
}
/**
* Returns the name of this type.
*
* @return string The name of this type
*/
public function getName()
{
return 'profile_service';
}
public function setUserServiceDetails($details)
{
$this->userServiceDetails = $details;
}
}
class ServiceDetailsType extends AbstractType
{
private $details;
public function __construct($details)
{
$this->details = $details;
}
/**
* @param \Symfony\Component\Form\FormBuilder $builder
* @param array $options
* @return void
*/
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('id', 'hidden')
->add('minPrice', 'money', array('required' => false))
->add('maxPrice', 'money', array('required' => false))
->add('unit', 'choice', array(
'choices' => array(
'hour' => 'Hours',
'photo' => 'Photos'
),
'required' => false
))
->add('unitsAmount', null, array('required' => false));
if (!empty($this->details)) {
$builder->setData($this->details);
}
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => 'Thestudioschedule\ProfileBundles\ServiceBundle\Entity\UserService',
'csrf_protection' => false
);
}
/**
* Returns the name of this type.
*
* @return string The name of this type
*/
function getName()
{
return 'profile_service_details';
}
}