Php 动态表单(开关实体)symfony2

Php 动态表单(开关实体)symfony2,php,jquery,ajax,symfony,doctrine-orm,Php,Jquery,Ajax,Symfony,Doctrine Orm,我正在做一页广告。广告可以是不同类型的,因此具有不同的数据。例如,车辆将有品牌和型号作为额外数据 现在,我有一个基本原则实体Advert,它包含每个广告所需的数据。不同的广告依次出现在这些数据中(doctrine2 discriminatormap) 我需要动态填充表单(使用ajax和symfony2表单),如果用户选择创建车辆广告,我希望显示车辆广告的选项。但是我还需要将实体更改为AdvertVehicle的形式 这可能吗?我确实在symfony2主页上读了食谱条目 “如何使用表单事件动态修改

我正在做一页广告。广告可以是不同类型的,因此具有不同的数据。例如,车辆将有
品牌
型号
作为额外数据

现在,我有一个基本原则实体
Advert
,它包含每个广告所需的数据。不同的广告依次出现在这些数据中(doctrine2 discriminatormap)

我需要动态填充表单(使用ajax和symfony2表单),如果用户选择创建车辆广告,我希望显示车辆广告的选项。但是我还需要将实体更改为
AdvertVehicle
的形式

这可能吗?我确实在symfony2主页上读了食谱条目

“如何使用表单事件动态修改表单”: 这应该通过对应用程序进行AJAX回调来处理。在该控制器中,您可以提交表单,但不必处理表单,只需使用提交的表单呈现更新的字段即可。然后可以使用来自AJAX调用的响应来更新视图

我知道如何向我的控制器发出ajax调用,我知道如何使用表单事件,但如何获得渲染选择框(例如包含车辆模型)的响应?用一种新的抽象类型?还是表单生成器

然后当用户实际提交表单时,我需要使用所选广告类型的实体。我可以根据用户在表单中的选择动态更改实体吗

编辑 我查了遗传表太好了,谢谢。我扩展了
AdvertType
并覆盖了
buildForm()
方法,在添加
AdvertVehicleType
所需的项之前,我调用父方法

进一步解释 每个广告实体都包含
价格
说明
标题
类别
。有些广告包含更多内容,如
制作
模型
。它们通过
判别图来区分(doctrine2)

示例:

// -- Entity
class CarAdvert extends Advert {

    protected $model;
    protected $make;

}

// -- Entity
// -- This uses discriminator mapping
class Advert {
    protected $title;
    protected $description;
    protected $price;
    protected $category;
}
如果用户选择了类别
cars
我想使用
CarAdvert
实体(用于验证和持久性)如果用户选择了house hold itemcategory我只想使用普通
广告
实体

一个主要的问题仍然是,我不知道如何通过ajax呈现扩展表单。这方面有什么建议吗?当用户选择car作为类别时,我希望表单得到更新(通过jQuery/ajax),但是如何制作一个控制器,只检索表单的扩展部分并将html作为响应发送回来(不使用细枝并在视图中呈现它,这可能吗)


解决方案:

// -- Entity
class CarAdvert extends Advert {

    protected $model;
    protected $make;

}

// -- Entity
// -- This uses discriminator mapping
class Advert {
    protected $title;
    protected $description;
    protected $price;
    protected $category;
}

请看下面的答案

解决方案:

// -- Entity
class CarAdvert extends Advert {

    protected $model;
    protected $make;

}

// -- Entity
// -- This uses discriminator mapping
class Advert {
    protected $title;
    protected $description;
    protected $price;
    protected $category;
}
我的问题的解决方案是在控制器中创建一些额外的函数,以解决我希望能够从用户选择中“动态”更改实体和表单的问题

public function indexAction(Request $request)
{
    $form = $this->getForm($request);
    $form->handleRequest($request);

    return array(
           'form' => $form->createView(),
           'request' => $request->request,
    );
}
其中
getForm
检索表单(例如,车辆的AdvertVehicleType或“默认”广告的AdvertType)

getForm
方法如下所示:

 private function getForm(Request $request)
{
    $categoryTitle = 'NONE';
    $categoryId = $request->request->get('advert', false)['category'];

    if ($categoryId) {
        $categoryTitle = $this->getDoctrine()->getRepository('Bundle:Category')->find($categoryId)->getTitle();
    }

    return $this->createForm($this->getFormType($categoryTitle), $this->getEntity($categoryTitle));
}

在这里,我检索
类别ID
(在请求的表单中选择)并使用getFormTypes检索formType,使用getEntity检索实体

private function getEntity($categoryTitle)
{
    $entity = new Advert();
    switch ($categoryTitle) {
        case Category::CARS:
            $entity = new AdvertCar();
    }

    return $entity;
}

private function getFormType($categoryTitle)
{
    switch ($categoryTitle) {
        case Category::CARS:
            return new AdvertCarType();
        default:
            return new AdvertType();
    }
}
为了能够使用ajax“动态”更新此表单(但如果用户尝试提交表单,它也可以工作),我在控制器中创建了另一个操作

此操作渲染我想要更新的表单部分(在ajax调用中),我通过使用twig将表单对象设置为如下方式渲染,从而实际挑出表单中不需要的内容:

{% do form.title.setRendered %}
(这只是一个例子,我实际上对所有不想渲染的表单对象都这样做

然后我就打电话:

{{ form_rest(form) }}
它将检索表单的“其余部分”,这对于不同的类别是不同的

现在让我们假设您有state和than town可供选择。首先选择state,然后在twig中呈现该州的城镇(但实际上您可以只呈现您需要的部分,例如
{form_row(form.towns)}}
,然后将呈现的模板作为json响应返回,并将其放入jquery所需的div中

$html = $this->renderView('@Bundle/NewAddPage/filter_area.twig', array('form' => $form->createView()));
然后在响应中返回$html变量


我希望这有帮助,并且解释足够好,如果不只是做一个注释,我会用我的答案更新它!

您可以在表单类型中使用继承,它可以避免为两个类似的表单重复代码。例如:
AdvertType
有2个字段。
AdvertVehicleType
可以扩展
AdvertType
,以获得一个dd 2字段。请告诉我们有关您的实体的更多信息,它们是如何声明的,您如何区分两种类型的
广告
,等等。关于这个问题@石棉有什么更新吗?我面临类似的问题,所以我对这个问题的可能解决方案或经验感兴趣,等等。谢谢!我希望更新后的答案足够好@acrobat不要犹豫如果您需要更多信息,请留下另一条评论!