2016-07-28 127 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