【问题标题】:ConstraintViolationListInterface to Exception in SymfonySymfony 中的 ConstraintViolationListInterface 异常
【发布时间】:2018-06-01 05:45:01
【问题描述】:

当验证失败时,我需要将ConstraintViolationListInterface 类型的对象转换为单个异常以进行进一步记录,其中消息是来自列表中每个约束违规的消息的串联。

显然,我不能使用验证在每个捆绑包中重复 foreach 循环来实现这一点,因此我正在考虑创建一个额外的捆绑包,提供一个接受 ConstraintViolationListInterface 的简单服务并返回一个异常。 Symfony 中是否有针对此问题的标准解决方案?我需要编写这个服务似乎很奇怪,这个问题似乎对我来说很常见。

【问题讨论】:

    标签: php symfony symfony-validator


    【解决方案1】:

    也许你可以像这样创建一个 ConstraintViolationsEvent :

    namespace AppBundle\Event;
    
    use Symfony\Component\EventDispatcher\Event;
    use Symfony\Component\Validator\ConstraintViolationListInterface;
    
    /**  
     * The order.placed event is dispatched each time an order is created
     * in the system.
     */
    class ConstraintViolationsEvent extends Event
    {
        const VIOLATIONS_DETECTED = 'constraint_violations.detected';
    
        protected $constraintViolationList;
    
        public function __construct(ConstraintViolationListInterface $constraintViolationList)
        {
            $this->constraintViolationList = $constraintViolationList;
        }
    
        public function getConstraintViolationList()
        {
            return $this->constraintViolationList;
        }
    }
    

    然后您可以为此事件创建一个侦听器,并在此侦听器中根据发现的所有违规情况创建您的异常。每次您发现违规行为时,您只需像这样在控制器中发送事件:

    class MyController extends Controller
    {
        public function myFormAction(Request $request)
        {
            /** handle the request, get the form data, validate the form...etc. **/
            $event = new ConstraintViolationsEvent($constraintViolationList);
            $dispatcher->dispatch(ConstraintViolationsEvent::VIOLATIONS_DETECTED, $event);
        }
    }
    

    事实上,您可以在服务中管理异常的创建并在侦听器中调用该服务。这取决于你。

    【讨论】:

      【解决方案2】:

      我也很惊讶 symfony 对此没有任何帮助,这就是我创建自定义异常的原因:

      class ValidationException extends \Exception
      {
          private $violations;
      
          public function __construct(array $violations)
          {
              $this->violations = $violations;
              parent::__construct('Validation failed.');
          }
      
          public function getMessages()
          {
              $messages = [];
              foreach ($this->violations as $paramName => $violationList) {
                  foreach ($violationList as $violation) {
                      $messages[$paramName][] = $violation->getMessage();
                  }
              }
              return $messages;
          }
      
          public function getJoinedMessages()
          {
              $messages = [];
              foreach ($this->violations as $paramName => $violationList) {
                  foreach ($violationList as $violation) {
                      $messages[$paramName][] = $violation->getMessage();
                  }
                  $messages[$paramName] = implode(' ', $messages[$paramName]);
              }
              return $messages;
          }
      }
      

      所有代码都可用here

      我在下一个方法中使用这个异常:

      try {
          $errors = $validator->validate(...);
          if (0 !== count($errors)) {
              throw new ValidationException($errors);
          }
      } catch (ValidationException $e) {
          // Here you can obtain your validation errors. 
          var_dump($e->getMessages());
      }
      

      【讨论】:

      • 问题只是与创建自定义异常有关,或者与如何正确处理检测到违规后引发的异常有关? @Sergey
      【解决方案3】:

      这个解决方案对我来说很好:

      protected function violationsToArray(ConstraintViolationListInterface $violations)
      {
          $messages = [];
      
          foreach ($violations as $constraint) {
              $prop = $constraint->getPropertyPath();
              $messages[$prop][] = $constraint->getMessage();
          }
      
          return $messages;
      }
      

      请注意,使用 $violations 数组键作为属性名称将不起作用:

          $messages = [];
      
          foreach ($violations as $prop => $constraint) {
              // $prop will not contain any value and this will not work as expected
              $messages[$prop][] = $constraint->getMessage();
          }
      

      【讨论】:

        猜你喜欢
        • 2012-09-19
        • 2012-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-09-26
        • 1970-01-01
        • 2021-12-19
        相关资源
        最近更新 更多