首页 后端开发 php教程 创建专注的领域应用程序。 Symfony 方法(管理验证错误)

创建专注的领域应用程序。 Symfony 方法(管理验证错误)

Nov 10, 2024 pm 05:23 PM

Creating focused domain applications. A Symfony approach (Managing validation errors)

介绍

在上一篇文章中,我们分析了 symfony 序列化器和验证器组件如何充当基础设施服务,为我们提供帮助我们在应用程序中执行常见任务的工具。我们还了解了为什么 UserInputDTO 类是属于我们域的元素,因为它包含业务规则以及如何创建应用程序层服务来执行提取和验证数据流。

在第二部分中,我们将了解如何管理验证错误,并且正如我们在第一部分中所做的那样,我们将识别哪些部分属于该域。

验证错误

按照使用验证约束建立的规则验证 UserInputDTO 后,Symfony 验证器组件将返回验证错误。

public function processData(string $content, string $dtoClass): object
{
     $requestData = json_decode($content, true);
     $userInputDTO = $serializer->denormalize($requestData, UserInputDTO::class);
     $errors = $validator->validate($userInputDTO);
     if(count($errors) > 0) {
         throw new ValidationFailedException($errors);
     }

     return $userInputDTO
}
登录后复制
登录后复制

正如您在上面的代码中看到的,如果验证方法发现错误,则会抛出 ValidationException 类型的异常。从这里开始,我们必须决定如何向用户显示错误(域/业务规则)以及我们将依赖哪些工具以便错误正确地到达用户(基础设施和应用程序)。

集中捕获验证错误

我们必须考虑的第一件事是,我们希望在验证错误发生时捕获它们。为了实现这一目标,我们将依赖基础设施层。
Symfony 内核附带了一组内置内核事件来监听特殊事件。其中一个事件是内核异常事件,当抛出异常时会触发该事件。让我们用它来捕获 ValidationException 错误。

class KernelSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            KernelEvents::EXCEPTION => 'onException'
        ];
    }

    public function onException(ExceptionEvent $event): void
    {
        $exception = $event->getThrowable();
        if($exception instanceof ValidationFailedException){
            // Business rules to build the errors
        }
    }
}
登录后复制
登录后复制

正如我们在上面的代码中看到的,KernelSubscriber 不断监听 KernelException 事件,并且仅当捕获的异常是 ValidationFailedException 类。 从这里开始,我们必须定义当
onException 方法检测到这是一个验证错误时将执行的逻辑。

创建域服务来构造错误数组

由于我们负责决定如何构建错误(我们定义这些业务规则),因此执行逻辑的服务将属于我们的域。让我们来编码吧


class ValidationErrorsBuilder {

    public function buildErrors(ValidationFailedException $exception): array
    {
        $errors = [];
        foreach ($exception->getViolations() as $violation) {
            $errors[$violation->getPropertyPath()] = $violation->getMessage();
        }

        return $errors;
    }
}
登录后复制
登录后复制

ValidationErrorsBuilder 代码非常简单:它循环违规错误并创建一个关联数组,其中键是生成错误的属性,值是错误消息。

使用 ValidationErrorsBuilder

现在是时候使用我们的 ValidationErrorsBuilder 域服务了。我们在 KernelSubscriber onException 方法上使用它。

public function processData(string $content, string $dtoClass): object
{
     $requestData = json_decode($content, true);
     $userInputDTO = $serializer->denormalize($requestData, UserInputDTO::class);
     $errors = $validator->validate($userInputDTO);
     if(count($errors) > 0) {
         throw new ValidationFailedException($errors);
     }

     return $userInputDTO
}
登录后复制
登录后复制

如您所见,在知道异常是 ValidationFailedException 后,我们使用域服务来获取验证错误数组。
现在,让我们看看下面的代码:

class KernelSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            KernelEvents::EXCEPTION => 'onException'
        ];
    }

    public function onException(ExceptionEvent $event): void
    {
        $exception = $event->getThrowable();
        if($exception instanceof ValidationFailedException){
            // Business rules to build the errors
        }
    }
}
登录后复制
登录后复制

我们添加了新行,在其中设置 Symfony JsonResponse 将错误数组保存为新响应,并指定返回的 HTTP 代码将是 400 Bad Request。
我们依赖 Symfony Response HTTP_BAD_REQUEST 常量来指定响应 HTTP 代码。由于我们在以域为中心的环境中工作,因此我们可以创建自定义域类(例如 php 枚举),但是,由于我们只需要处理标准 HTTP 代码并且没有特定的自定义需求,因此我们可以使用Symfony HTTP 代码虽然这让我们更加依赖这个框架。

那么应用层呢?

到目前为止我们还没有讨论应用层。我们在文章一开始就说过,Symfony 框架附带了一个有用的内置事件,例如我们使用的事件:内核异常事件。此外,symfony框架还为我们提供了EventSubscriberInterface,通过它我们可以创建自定义事件订阅者并监听我们需要的事件。
从这些信息中,我们可以得出结论,symfony 为我们提供了内核异常事件和 EventSubscriberInterface 但我们必须使用该接口来创建订阅者,指定我们要监听哪些事件。让我们继续:

  • 事件订阅者指定我们监听内核异常事件。
  • 事件订阅者检查异常是否是 ValidationFailedException.
  • 的实例
  • 事件订阅者使用域服务来构建错误数组。
  • 事件订阅者创建包含错误的 JsonResponse 并将其设置为最终响应。

这听起来很熟悉吗?是的,事件订阅者负责在抛出异常后管理验证错误的编排和协调,因此我们可以说事件订阅者将充当应用程序服务。
如果我们想更进一步,我们可以创建一个应用程序层服务并在订阅者中使用它。

class ValidationErrorsBuilder {

    public function buildErrors(ValidationFailedException $exception): array
    {
        $errors = [];
        foreach ($exception->getViolations() as $violation) {
            $errors[$violation->getPropertyPath()] = $violation->getMessage();
        }

        return $errors;
    }
}
登录后复制
登录后复制
public function onException(ExceptionEvent $event): void
{
    $exception = $event->getThrowable();
    if($exception instanceof ValidationFailedException){
       $errors = $this->validationErrorsBuilder->buildErrors($exception);
    }
}
登录后复制

现在,ValidationErrorsProcessor 将充当协调验证错误响应管理并使用 ValidationErrorsBuilder 域服务的应用程序服务。

结论

在本系列的第二篇文章中,我们已经确定了验证错误管理过程的哪些组件属于该域、我们使用了基础设施的哪些元素以及内核订阅者如何充当应用程序服务。
下一篇我们会将实体持久化到数据库中,并分析如何分离将DTO转换为可持久化实体的逻辑。

以上是创建专注的领域应用程序。 Symfony 方法(管理验证错误)的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

<🎜>:泡泡胶模拟器无穷大 - 如何获取和使用皇家钥匙
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系统,解释
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆树的耳语 - 如何解锁抓钩
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1671
14
CakePHP 教程
1428
52
Laravel 教程
1331
25
PHP教程
1276
29
C# 教程
1256
24
说明PHP中的安全密码散列(例如,password_hash,password_verify)。为什么不使用MD5或SHA1? 说明PHP中的安全密码散列(例如,password_hash,password_verify)。为什么不使用MD5或SHA1? Apr 17, 2025 am 12:06 AM

在PHP中,应使用password_hash和password_verify函数实现安全的密码哈希处理,不应使用MD5或SHA1。1)password_hash生成包含盐值的哈希,增强安全性。2)password_verify验证密码,通过比较哈希值确保安全。3)MD5和SHA1易受攻击且缺乏盐值,不适合现代密码安全。

PHP和Python:比较两种流行的编程语言 PHP和Python:比较两种流行的编程语言 Apr 14, 2025 am 12:13 AM

PHP和Python各有优势,选择依据项目需求。1.PHP适合web开发,尤其快速开发和维护网站。2.Python适用于数据科学、机器学习和人工智能,语法简洁,适合初学者。

PHP行动:现实世界中的示例和应用程序 PHP行动:现实世界中的示例和应用程序 Apr 14, 2025 am 12:19 AM

PHP在电子商务、内容管理系统和API开发中广泛应用。1)电子商务:用于购物车功能和支付处理。2)内容管理系统:用于动态内容生成和用户管理。3)API开发:用于RESTfulAPI开发和API安全性。通过性能优化和最佳实践,PHP应用的效率和可维护性得以提升。

PHP类型提示如何起作用,包括标量类型,返回类型,联合类型和无效类型? PHP类型提示如何起作用,包括标量类型,返回类型,联合类型和无效类型? Apr 17, 2025 am 12:25 AM

PHP类型提示提升代码质量和可读性。1)标量类型提示:自PHP7.0起,允许在函数参数中指定基本数据类型,如int、float等。2)返回类型提示:确保函数返回值类型的一致性。3)联合类型提示:自PHP8.0起,允许在函数参数或返回值中指定多个类型。4)可空类型提示:允许包含null值,处理可能返回空值的函数。

PHP的持久相关性:它还活着吗? PHP的持久相关性:它还活着吗? Apr 14, 2025 am 12:12 AM

PHP仍然具有活力,其在现代编程领域中依然占据重要地位。1)PHP的简单易学和强大社区支持使其在Web开发中广泛应用;2)其灵活性和稳定性使其在处理Web表单、数据库操作和文件处理等方面表现出色;3)PHP不断进化和优化,适用于初学者和经验丰富的开发者。

PHP和Python:解释了不同的范例 PHP和Python:解释了不同的范例 Apr 18, 2025 am 12:26 AM

PHP主要是过程式编程,但也支持面向对象编程(OOP);Python支持多种范式,包括OOP、函数式和过程式编程。PHP适合web开发,Python适用于多种应用,如数据分析和机器学习。

您如何防止PHP中的SQL注入? (准备的陈述,PDO) 您如何防止PHP中的SQL注入? (准备的陈述,PDO) Apr 15, 2025 am 12:15 AM

在PHP中使用预处理语句和PDO可以有效防范SQL注入攻击。1)使用PDO连接数据库并设置错误模式。2)通过prepare方法创建预处理语句,使用占位符和execute方法传递数据。3)处理查询结果并确保代码的安全性和性能。

PHP和Python:代码示例和比较 PHP和Python:代码示例和比较 Apr 15, 2025 am 12:07 AM

PHP和Python各有优劣,选择取决于项目需求和个人偏好。1.PHP适合快速开发和维护大型Web应用。2.Python在数据科学和机器学习领域占据主导地位。

See all articles