0

我有这个架构结构:

  • 报告-> id,预测
  • 预测-> id、user_id、bricks、products
  • 砖块-> id、区域、计划
  • 计划-> id、区域、目标
  • 目标-> id、产品、valueA、valueB、评论
  • 评论-> id、目标、用户、消息、createdAt
  • 产品-> id、预测、目标、值C
  • 区域-> id、name、bricks
  • 区域-> id、名称、计划

我正在用我的自定义 FormType编辑一个预测。

预测网格类型:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('bricks', 'collection', array(
        'type' => 'forecast_grid_brick',
    ));

    $builder->add('products', 'collection', array(
        'type' => 'forecast_grid_product',
    ));
}

ForecastGridBrick 类型:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('plans', 'collection', array(
        'type' => 'forecast_grid_plan',
    ));
}

ForecastGridProductType:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('valueC', 'number', array(
            'autocomplete'  => false,
            'attr'          => array(
                'class' => 'grid-mini positive-integer'
            ),
        ));
}

预测网格计划类型:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('targets', 'collection', array(
        'type' => 'forecast_grid_target',
    ));
}

预测网格目标类型:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('valueA', 'number', array(
            'autocomplete'  => false,
            'attr'          => array(
                'class' => 'grid-mini positive-integer'
            )
        ))
        ->add('valueB', 'number', array(
            'autocomplete'  => false,
            'attr'          => array(
                'class' => 'grid-mini positive-integer'
            )
        ))
        ->add('comments', 'collection', array(
            'type'          => 'forecast_grid_comment',
            'allow_add'     => true,
            'allow_delete'  => false
        ));
}

预测网格评论类型:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('message', 'text', array(
            'autocomplete'  => false,
            'required'      => false,
            'attr'          => array(
                'class'       => 'grid-mini',
                'disabled'    => 'disabled',
            ),
        ));
}

当然所有表单类型都data_class设置为相应的类,我只是没有包含其他方法以使其尽可能短。

创建和查看表单不是问题,symfony 处理它很快(不到 0.5 秒)。问题是当我发送表格时:

public function updateAction($id)
{
    $forecast = $this->getDoctrine()
        ->getRepository('AcmeForecastBundle:Forecast')
        ->find($id);

    $this->checkCredentials('canEditForecastGrid(object)', $forecast);

    if (!$forecast) {
        throw new NotFoundHttpException("The Acme\ForecastBundle\Entity\Forecast with id $id can't be found");
    }

    $form = $this->createForm('forecast_grid', $forecast);

    $form->handleRequest($this->getRequest()); // this makes my server hang

    echo 'This part is never reached'; exit;
    if ($form->isValid()) {
        // etc

所以..在帖子中我有:

[forecast_grid] => array(
    [products] => array(
        // contains 6 products each with 1 field: valueC, example below
        [0] => array(
            [valueC] => "X"
        )
    ),
    [bricks] => array(
        // contains 10 bricks, each with 1 field: plans, example below
        [0] => array(
            [plans] => array(
                // contains various amount of plans
                // some bricks have 2 plans, some have 30
                // all together there are approx 120 plans in the form
                [0] => array(
                    [targets] => array(
                        // contains 6 targets, 1 for each product
                        // each with 3 fields: valueA, valueB, comments, example:
                        [0] => array(
                             [valueA] = "Y",
                             [valueB] = "Z",
                             [comments] => array(
                                 // contains  1 or 0 comments,
                                 // only one (new) comment is submitted
                                 // existing comments don't need to be 
                                 // submitted becouse of "allow_delete" => false
                                 // option, example below:
                                 [0] => array(
                                     [message] => "My comment"
                                 )
))))))))

所以.. 我们有 120 个计划 x 6 个目标 x 2 个字段 => 1440 个字段,加上 6 个产品 x 1 个字段 = 6 个字段,加上(最多)120 个计划 x 6 个目标 x 1 个评论 = 720 个字段。

这给了我们 2166 个字段。现在是不是太多了?

我已经做了一些测试和 Instatiationg 10000 stdClasses,assingning 20 个字段并在每个字段上运行 preg_match ......瞬间。我知道该框架的功能不止于此,但我认为这么多字段对 PHP 来说应该不是问题。

当你得到的唯一的东西是 max_execution_time 错误(没有 symfony 分析器:<)或你的 apache2 挂起时,很难调试。

致命错误:第 943 行 (...)/vendor/symfony/symfony/src/Symfony/Component/Form/Form.php 中的最大执行时间超过 30 秒

我的问题是:

  • 试图一次性提交这么多字段是错误的(symfony2 表单组件从未构建用于处理此类任务)?
  • 或 symfony2应该毫无问题地处理该表单,这意味着错误的根源在于其他地方(doctrine2 hydration?).. 如果是这样.. 它可能在哪里,我如何测试是否是这种情况?

有些人建议我使用 AJAX 单独提交每个计划(有 6 个目标)。我可能会这样做,因为我的时间不多了,但我仍然有兴趣知道答案 -> symfony2 表单组件是否有任何已知的性能限制?

4

1 回答 1

2

在考虑和测试了许多方法后,我决定使用 AJAX 并一次保存一项。我已经设法将保存 2000 多个字段的操作时间缩短到 5 秒(这证明了 symfony 的能力,太好了!),我相信性能仍有改进的空间,要做到这一点我必须:

  • 将最大输入、最大执行时间、最大上传大小等的 php.ini 和 apache2.conf 限制提高到极高的值
  • 禁用许多OWASP规则(这会削弱服务器对各种攻击的保护)
  • 将应用程序逻辑和数据库模式更改为可读性/可维护性较低(但性能更好)
  • 花太多时间在和测试这样简单的功能上

我的结论是:可以做到,但不值得麻烦。最好用 AJAX 来做。

并回答这个问题:是的,有一个限制。这取决于许多变量,但一般来说,如果您尝试一次保存 1000 多个字段,您应该会遇到麻烦。

于 2013-08-29T09:31:18.900 回答