0

0

PHP 枚举:从字符串获取非 Backed Enum 案例的实现方法

花韻仙語

花韻仙語

发布时间:2025-11-28 11:57:35

|

770人浏览过

|

来源于php中文网

原创

PHP 枚举:从字符串获取非 Backed Enum 案例的实现方法

本文旨在解决在 php 中如何根据字符串名称获取非 backed enum 的枚举案例。由于非 backed enum 不支持 `tryfrom` 或 `from` 方法,文章将详细介绍通过自定义静态方法遍历枚举所有案例并进行名称匹配的实现方案,并提供示例代码和相关注意事项,帮助开发者有效管理和使用非 backed enum。

PHP 枚举基础与 Backed Enum 的区别

PHP 8.1 引入了枚举(Enums),为开发者提供了一种定义一组命名常量的新方式。在 PHP 中,枚举分为两种主要类型:

  1. 纯枚举(Pure Enums / Plain Enums):这类枚举只包含案例名称,没有关联的具体值。例如:

    对于纯枚举的案例,可以通过 Status::OK->name 获取其字符串名称 "OK"。

  2. 支持值枚举(Backed Enums):这类枚举的每个案例都关联一个具体的值,可以是字符串或整数。例如:

    立即学习PHP免费学习笔记(深入)”;

    支持值枚举的案例除了 name 属性外,还拥有 value 属性,例如 Status::OK->value 将返回 "success"。更重要的是,Backed Enums 提供了 from() 和 tryFrom() 静态方法,允许开发者通过关联值(而非案例名称)直接获取对应的枚举案例。例如 Status::tryFrom("success") 将返回 Status::OK。

问题:从字符串获取非 Backed Enum 案例

开发中常见的一种需求是,给定一个字符串(通常是枚举案例的名称),需要获取对应的枚举案例实例。对于 Backed Enum,如果字符串恰好是其关联值,可以直接使用 tryFrom() 方法。然而,对于纯枚举,我们没有关联值,也无法直接使用 tryFrom() 方法(因为它期望的是关联值而不是案例名称)。

例如,我们希望实现类似 Status::get("OK") 的功能,使其返回 Status::OK 实例,但又不希望将 Status 定义为 Backed Enum(即避免 case OK = "OK"; 这种重复定义)。

解决方案:自定义静态查找方法

由于 PHP 的纯枚举没有内置的通过名称查找案例的方法,最直接和推荐的解决方案是在枚举类内部实现一个自定义的静态方法来完成此功能。核心思路是遍历枚举的所有案例,并比较每个案例的 name 属性与传入的字符串是否匹配。

以下是一个实现此功能的示例代码:

name === $normalizedName) {
                return $status; // 找到匹配项,返回该案例
            }
        }

        // 未找到匹配的案例则返回 null
        return null;
    }
}

// 示例用法
$statusOk = Status::get("OK"); // 返回 Status::OK
$statusFailed = Status::get("  failed  "); // 经过内部处理,返回 Status::FAILED
$statusPending = Status::get("pending"); // 经过内部处理,返回 Status::PENDING
$statusNotFound = Status::get("UNKNOWN"); // 未找到,返回 null

var_dump($statusOk);
var_dump($statusFailed);
var_dump($statusPending);
var_dump($statusNotFound);

// 输出示例:
// object(Status)#1 (0) {
// }
// object(Status)#2 (0) {
// }
// object(Status)#3 (0) {
// }
// NULL
?>

代码解析:

  1. public static function get(string $name): ?Status
    • 定义了一个公共的静态方法 get,可以直接通过类名调用(Status::get(...))。
    • 它接受一个字符串 $name 作为参数,表示要查找的枚举案例名称。
    • 返回类型 ?Status 表示该方法可能返回 Status 类的实例,也可能返回 null(如果未找到匹配的案例)。
  2. $normalizedName = strtoupper(trim($name));
    • 这是一个重要的预处理步骤。trim() 函数用于去除字符串两端的空白字符,strtoupper() 函数将字符串转换为大写。
    • 这样做是为了增强查找的健壮性,使得输入 'ok'、' OK ' 或 'pending' 都能正确匹配到 Status::OK 或 Status::PENDING,而无需严格区分大小写和空白。
  3. if (empty($normalizedName)) { return null; }
    • 处理了输入字符串为空或仅包含空白字符的情况,避免不必要的遍历和潜在错误。
  4. foreach (self::cases() as $status)
    • self::cases() 是 PHP 枚举内置的静态方法,它返回一个包含所有枚举案例实例的数组。
    • 通过 foreach 循环,我们可以逐一访问枚举中的每个案例。
  5. if ($status->name === $normalizedName)
    • 在循环内部,我们将当前枚举案例的 name 属性(例如 Status::OK->name 结果为 "OK")与经过标准化处理的输入名称 $normalizedName 进行严格比较。
    • 如果匹配成功,则说明找到了对应的枚举案例,立即将其返回。
  6. return null;
    • 如果循环结束后仍未找到匹配的案例,则表示传入的名称无效,方法返回 null。

注意事项与最佳实践

  • 大小写敏感性处理: 在实际应用中,用户输入可能不区分大小写。如示例所示,通过 strtoupper() 或 strtolower() 统一处理输入和枚举案例名称,可以提高查找的灵活性和用户体验。
  • 输入校验: 始终对用户输入进行校验。本例中通过 empty($normalizedName) 进行了初步检查。
  • 返回类型: 明确指定返回类型为 ?Status (Nullable Type),清晰地表明方法可能返回 null,这有助于代码的静态分析和提高可读性。
  • 性能考量: 对于大多数应用场景,枚举的案例数量通常不会非常庞大(例如几十个到几百个)。在这种情况下,遍历 self::cases() 数组的性能开销可以忽略不计。如果枚举案例数量极端庞大(例如数千个以上,这种情况在实际开发中非常罕见),并且此查找操作是性能瓶颈,可以考虑在枚举类中维护一个静态的查找映射(例如 private static array $lookupMap;),在第一次调用时构建,后续直接查询映射表。但对于常规使用,自定义遍历方法已足够高效。
  • 代码可读性与封装: 将查找逻辑封装在枚举类内部,不仅提高了代码的可读性,也遵循了面向对象的设计原则,使枚举类更加内聚和易于管理。

总结

尽管 PHP 的纯枚举没有像 Backed Enum 那样内置 tryFrom() 或 from() 方法来通过字符串名称获取案例,但通过在枚举类中实现一个自定义的静态查找方法,可以优雅且高效地解决这一问题。这种方法利用了 self::cases() 提供的所有枚举案例列表,结合字符串处理和比较逻辑,实现了灵活的案例查找功能,同时保持了代码的清晰性和可维护性。理解纯枚举和 Backed Enum 的区别,并根据具体需求选择合适的实现方式,是有效利用 PHP 枚举的关键。

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2452

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1573

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1475

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

951

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1414

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1234

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1445

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1305

2023.11.13

jQuery 正则表达式相关教程
jQuery 正则表达式相关教程

本专题整合了jQuery正则表达式相关教程大全,阅读专题下面的文章了解更多详细内容。

1

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 8.5万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 6.9万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号