首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >PHP 中的策略枚举

PHP 中的策略枚举

作者头像
Tinywan
发布2026-07-01 12:39:54
发布2026-07-01 12:39:54
140
举报
文章被收录于专栏:开源技术小栈开源技术小栈

引言

枚举(通常称为 Enums)是软件开发中的一个强大工具,如果正确使用,它可以在应用程序的架构设计中发挥重要作用。长期以来,PHP 没有支持这种数据类型,但从 PHP 8.1 开始,我们终于添加了它,这带来了许多可能性。在本文中,让我们回顾如何战略性地使用它们来改进我们的应用程序。

为什么使用枚举

基本上,枚举是一种数据类型,它作为一个预定义常量的集合。例如,如果我们正在构建一个 ToDo 应用程序,我们可以使用 枚举 来表示任务的优先级。

代码语言:javascript
复制
1 enum Priority
2 {
3    case LOW;
4    case NORMAL;
5    case HIGH;
5 }

使用 枚举 来表示任务的优先级已经为我们的设计带来了重要的改进,而不是使用字符串来表示它,我们可以将它作为 Task 实体中的类型使用,因此在代码库中处理这个实体时,我们可以轻松识别优先级属性的可能值,而不必猜测或检查数据库。

代码语言:javascript
复制
1 final class Task
2 {
3    public function __construct(
4        public string $title,
5        public string $description,
6        public Priority $priority,
7    ) {
8    }
9 }
10
11 $task = new Task(
12    title: 'My First Task',
13    description: 'Do something',
14    priority: Priority::HIGH,
15 );

但是上面的代码在处理数据库时有一个问题,因为 枚举 是由对象表示的,我们无法轻松地将它用于保存数据到数据库中,但我们有另一种类型的 枚举 来拯救局面。

支持后备值的枚举

如上所述,枚举 是由对象表示的,但 PHP 还支持 支持后备值的枚举(Backed Enums),它们可以分配一个值。内部它们仍然是由对象表示的,但由于它们是由值表示的,我们可以轻松使用这个值来序列化枚举,例如保存到数据库中。让我们改进我们的 Priority 枚举,并将其转换为 支持后备值的枚举

代码语言:javascript
复制
1 enum Priority: string
2 {
3    case LOW = 'low';
4    case NORMAL = 'normal';
5    case HIGH = 'high';
6 }

Task 实体的实例化可以保持与之前相同,并且仍然有效,但我们也可以以不同的方式使用它。想象一下,我们从 UI 接收优先级作为一个字符串值,并在实例化 Task 实体时需要分配枚举。我们可以使用这种方法:

代码语言:javascript
复制
1  $task = new Task(
2    title: 'My First Task',
3    description: 'Do something',
4    priority: Priority::from($priority),
5 );

请记住,我们只能为 支持后备值的枚举 使用 stringint 类型。

枚举方法

就像普通类一样,我们也可以在枚举中定义方法,当我们将 match 操作符与这些方法结合使用时,这带来了许多可能性。想象一下,现在我们想为 ToDo 应用程序中的每个优先级分配一个特定的颜色。我们可以通过在 Priority 枚举中创建一个方法来轻松实现这一点。

代码语言:javascript
复制
1 enum Priority: string
2 {
3    case LOW = 'low';
4    case NORMAL = 'normal';
5    case HIGH = 'high';
6
7    public function color(): string
8    {
9        match ($this) {
10            self::LOW => 'green',
11            self::NORMAL => 'blue',
12            self::HIGH => 'red',
13        };
14    }
15 }
16
17 $task = new Task(
18    title: 'My First Task',
19    description: 'Do something',
20    priority: Priority::HIGH,
21 );
22
23 $task->priority->color();
24 // 'red'

进一步扩展枚举方法

我们上面看到,我们可以在枚举中定义方法,这为我们的应用程序打开了许多可能性。我们看到的例子只是为优先级返回一个特定的颜色,但我们可以通过这些方法进一步扩展这个边界。

想象一下,我们需要为每个任务向用户发送通知,但每个优先级的通知类型不同。我们有许多不同的方式来处理这种情况,其中一种解决方案是使用我们的 Priority 枚举来获取所需的正确类型的通知发送器。首先,我们需要为通知发送器定义一个契约。

代码语言:javascript
复制
1 interface NotificationSender
2 {
3    public function send(Task $task): void;
4 }

现在我们已经定义了契约,我们需要实现我们需要的每种类型的发送器,为这个例子的简单起见,我不会提供这些实现的代码,只列出我们可能拥有的不同实现。

代码语言:javascript
复制
1 final class EmailSender implements NotificationSender
2 {
3    public function send(Task $task): void
4    {
5        // Send email logic here
6    }
7 }
8
9 final class SlackSender implements NotificationSender
10 {
11    public function send(Task $task): void
12    {
13        // Send slack notification logic here
14    }
15 }
16
17 final class PhoneMessageSender implements NotificationSender
18 {
19    public function send(Task $task): void
20    {
21        // Send SMS logic here
22    }
23 }

现在有了我们的通知发送器实现,我们可以在 Priority 枚举中实现一个简单的方法,它将为每个优先级类型检索正确的发送器。

代码语言:javascript
复制
1 enum Priority: string
2 {
3    case LOW = 'low';
4    case NORMAL = 'normal';
5    case HIGH = 'high';
6
7    public function notificationSender(): NotificationSender
8    {
9        match ($this) {
10            self::LOW => new EmailSender(),
11            self::NORMAL => new SlackSender(),
12            self::HIGH => new PhoneMessageSender(),
13        };
14    }
15 }

使用这个简单的方法,在创建新任务时,我们可以轻松使用下面的方法发送通知。

代码语言:javascript
复制
1 task = new Task(
2    title: 'My First Task',
3    description: 'Do something',
4    priority: Priority::HIGH,
5 );
6 
7 $task->priority->notificationSender()->send($task);

结论

如你所见,枚举 为我们提供了无限的可能性来改进我们的应用程序,如果我们明智地使用它们,我们可以设计出更干净、更易维护的代码库。我的目标是通过本文展示,我们可以超越简单的辅助函数,如获取颜色或标签,而是使用 枚举 来解决更复杂的问题,并将它们作为应用程序 架构设计 的核心部分。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-12-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 开源技术小栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • 为什么使用枚举
  • 支持后备值的枚举
  • 枚举方法
  • 进一步扩展枚举方法
  • 结论
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档