如何基于SOLID原则优化PHP 8.1枚举处理用户输入的逻辑?
基于SOLID原则优化PHP枚举的复用逻辑
首先,你当前通过循环匹配枚举值的做法不仅冗余,还违反了单一职责原则——视图层不该承担枚举实例查找的业务逻辑,同时重复的循环代码也不符合DRY(Don't Repeat Yourself)原则。以下是符合SOLID的优化方案:
1. 把查找逻辑封装到枚举类内部(开闭+单一职责)
在PaymentMethods枚举中添加静态方法,将"通过name获取枚举实例"的逻辑封装到枚举自身,这样所有需要该逻辑的地方都能直接调用,且后续新增支付方式只需修改枚举类,无需改动外部代码(符合开闭原则)。
enum PaymentMethods : string { case PAYPAL = 'pay with paypal'; case STRIPE = 'pay with stripe'; /** * 通过name获取枚举实例 * @param string $name * @return self|null */ public static function fromName(string $name): ?self { foreach (self::cases() as $case) { if ($case->name === $name) { return $case; } } return null; } }
2. 简化视图中的调用逻辑
现在视图里不用再写循环,直接调用枚举的静态方法即可,配合PHP 8.0+的null安全运算符避免空值报错:
<p>{{ PaymentMethods::fromName(request()->get('payment_method'))?->value }}</p>
3. 封装视图复用逻辑(依赖倒置+单一职责)
如果多处视图都需要渲染支付方式选择框或显示选中的支付方式,可以用Laravel的自定义Blade指令或视图组件进一步封装,彻底消除重复代码:
示例:自定义Blade指令
在AppServiceProvider的boot方法中注册指令:
use Illuminate\Support\Facades\Blade; use App\Enums\PaymentMethods; public function boot() { // 渲染支付方式选择框 Blade::directive('paymentSelect', function ($fieldName = "'payment_method'") { return "<?php echo '<select name=' . $fieldName . '>'; foreach (PaymentMethods::cases() as \$case) { \$selected = request()->get($fieldName) === \$case->name ? 'selected' : ''; echo '<option value=\"' . \$case->name . '\" ' . \$selected . '>' . \$case->value . '</option>'; } echo '</select>'; ?>"; }); // 显示选中的支付方式名称 Blade::directive('paymentLabel', function ($fieldName = "'payment_method'") { return "<?php \$method = PaymentMethods::fromName(request()->get($fieldName)); echo \$method ? \$method->value : '未选择支付方式'; ?>"; }); }
之后在任意视图中只需一行代码即可复用:
<!-- 渲染支付方式选择框 --> @paymentSelect <!-- 显示选中的支付方式 --> <p>@paymentLabel</p>
4. 配合表单验证增强健壮性(里氏替换)
在Laravel表单请求中验证支付方式的合法性,确保传入的是有效的枚举name,避免无效值进入业务逻辑:
use App\Enums\PaymentMethods; use Illuminate\Validation\Rules\Enum; public function rules() { return [ 'payment_method' => ['required', new Enum(PaymentMethods::class)], ]; }
符合的SOLID原则说明
- 单一职责:枚举类负责自身实例的管理,视图层仅负责展示,指令负责渲染逻辑,各模块职责清晰。
- 开闭原则:新增支付方式只需修改枚举类,无需改动查找逻辑、视图或验证代码。
- 依赖倒置:视图和指令依赖抽象的枚举类,而非具体的循环逻辑,降低模块间耦合。
内容的提问来源于stack exchange,提问作者Mehran Nasr
相关产品推荐
相关产品推荐

