2016-07-28 129 views
1

我想构建一个将Symfony表单错误转换为可以序列化的多维数组的方法。Symfony形式子代的递归循环

目前我只有一个窗体(fieldset类型)中的窗体。我创建了一个用于在表单中嵌入N个表单的新系统。我需要能够遍历所有有错误的孩子来填充$errors数组。

我需要跟踪深度或穿过的距离。

例如,表单中的表单应为$errors[depth1][depth2]['message']。具有多个嵌入表单(例如最多5个)的表单将是$errors[depth1][depth2][depth3][depth4][depth5]['message']$errors[depth1][depth2] e.t.c.

注意:[depth(N)]将被替换为当前的表单名称。

什么是最干净的方式来做到这一点。

这是我现在的函数,它可以获取字段集,但是我能够在不管深度如何获得任何错误并保持位置(键)完整?

private static function getFieldSetErrors(Form $form, &$errors) 
    { 
     foreach ($form->all() as $formField) { 
      if ($formField->getConfig()->getType()->getInnerType() instanceof FieldsetComponentType) { 
       // ...then loop over the fields to extract any errors. 
       foreach ($formField as $element) { 
        foreach ($element->getErrors() as $error) { 
         $errors[$formField->getName()][$element->getName()]['message'] = $error->getMessage(); 
         $errors[$formField->getName()][$element->getName()]['messageTemplate'] = $error->getMessageTemplate(); 
         $errors[$formField->getName()][$element->getName()]['messagePluralization'] = $error->getMessagePluralization(); 
         $errors[$formField->getName()][$element->getName()]['messageParameters'] = $error->getMessageParameters(); 
         $errors[$formField->getName()][$element->getName()]['cause'] = $errors[$formField->getName()][$element->getName()]; 
         if ($errorCause = $error->getCause()) { 
          $errors[$formField->getName()][$element->getName()]['cause']['plural'] = $errorCause->getPlural(); 
          $errors[$formField->getName()][$element->getName()]['cause']['propertyPath'] = $errorCause->getPropertyPath(); 
          $errors[$formField->getName()][$element->getName()]['cause']['invalidValue'] = $errorCause->getInvalidValue(); 
          $errors[$formField->getName()][$element->getName()]['cause']['constraint'] = serialize($errorCause->getConstraint()); 
          $errors[$formField->getName()][$element->getName()]['cause']['code'] = $errorCause->getCode(); 
          $errors[$formField->getName()][$element->getName()]['cause']['cause'] = $errorCause->getCause(); 
         } 
        } 
       } 
      } 
     } 
    } 

它可能看起来像:

private static function getFieldErrorsRecursively(Form $form, &$errors, $position = []) 
    { 
     foreach ($form as $child) { 
      $fieldsArray = $child->getConfig()->getOptions()['fields'] ?? []; 
      if (count($fieldsArray) === 0) { 
       if (!$child->isValid()) { 
        foreach ($child->getErrors() as $error) { 
         $errors[$child->getName()]['message'] = $error->getMessage(); 
         $errors[$child->getName()]['messageTemplate'] = $error->getMessageTemplate(); 
         $errors[$child->getName()]['messagePluralization'] = $error->getMessagePluralization(); 
         $errors[$child->getName()]['messageParameters'] = $error->getMessageParameters(); 
         $errors[$child->getName()]['cause'] = $errors[$child->getName()]; 
         if ($errorCause = $error->getCause()) { 
          $errors[$child->getName()]['cause']['plural'] = $errorCause->getPlural(); 
          $errors[$child->getName()]['cause']['propertyPath'] = $errorCause->getPropertyPath(); 
          $errors[$child->getName()]['cause']['invalidValue'] = $errorCause->getInvalidValue(); 
          $errors[$child->getName()]['cause']['constraint'] = serialize($errorCause->getConstraint()); 
          $errors[$child->getName()]['cause']['code'] = $errorCause->getCode(); 
          $errors[$child->getName()]['cause']['cause'] = $errorCause->getCause(); 
         } 
        } 

        return true; 
       } 
      } elseif (count($fieldsArray) > 0) { 
       self::getFieldErrorsRecursively($child, $errors, $child->getName()); 

       if (count($errors) > 0) { 
        return true; 
       } 

       return true; 
      } 
     } 

     return false; 
    } 

任何帮助,将不胜感激:)

+0

不要(跟踪)。构建一个递归函数,该函数被数组调用,并使用嵌套数组调用它自己。如果你通过引用传递,你总是可以使用'$ errors ['cause'] ..' – kero

+0

我想我必须跟踪位置,但是当我再次应用它时,我需要知道窗体中的深度当将错误应用到它的原始字段时。 – Kal

+0

也许我不需要跟踪是否仅通过搜索匹配原始原因字段的字段来应用它们? – Kal

回答

1

Symfony provides a function for this

// a FormErrorIterator instance representing the form tree structure 
$errors = $form->getErrors(true, false); 
+0

这是可爱的,它确实整理了代码。虽然我认为我仍然不得不递归地写一些东西,因为你不能序列化该函数的输出,因为它包含闭包。 – Kal