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):这类枚举只包含案例名称,没有关联的具体值。例如:

    <?php
    enum Status
    {
        case OK;
        case FAILED;
        case PENDING;
    }
    ?>

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

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

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

    <?php
    enum Status: string // 指定关联值为字符串类型
    {
        case OK = "success";
        case FAILED = "failure";
        case PENDING = "waiting";
    }
    ?>

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

    Cardify卡片工坊
    Cardify卡片工坊

    使用Markdown一键生成精美的小红书知识卡片

    下载

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

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

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

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

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

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

<?php
enum Status
{
    case OK;
    case FAILED;
    case PENDING;

    /**
     * 根据字符串名称获取对应的枚举案例。
     *
     * @param string $name 要查找的枚举案例名称。
     * @return Status|null 如果找到匹配的案例,则返回该案例实例;否则返回 null。
     */
    public static function get(string $name): ?Status
    {
        // 对输入名称进行清理,例如转换为大写并去除空白,以实现更灵活的匹配。
        // 这样做可以处理 "ok", "  OK  " 等不同格式的输入。
        $normalizedName = strtoupper(trim($name));

        // 避免空字符串查询导致不必要的遍历
        if (empty($normalizedName)) {
            return null;
        }

        // 遍历枚举类的所有案例
        foreach (self::cases() as $status) {
            // 比较枚举案例的名称属性与标准化后的输入名称
            if ($status->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 枚举的关键。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1051

2023.08.02

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

254

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1110

2024.03.01

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1570

2023.10.24

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

847

2023.08.22

php中foreach用法
php中foreach用法

本专题整合了php中foreach用法的相关介绍,阅读专题下面的文章了解更多详细教程。

268

2025.12.04

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

58

2025.09.05

java面向对象
java面向对象

本专题整合了java面向对象相关内容,阅读专题下面的文章了解更多详细内容。

65

2025.11.27

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

49

2026.03.13

热门下载

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

精品课程

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

共137课时 | 13.6万人学习

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

共6课时 | 11.3万人学习

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

共13课时 | 1.0万人学习

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

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